Преглед изворни кода

Added ScrollBar to better handle scrollviewer

David Catuhe пре 6 година
родитељ
комит
e0609c6546

+ 2 - 2
gui/src/2D/controls/button.ts

@@ -51,8 +51,8 @@ export class Button extends Rectangle {
         this.thickness = 1;
         this.thickness = 1;
         this.isPointerBlocker = true;
         this.isPointerBlocker = true;
 
 
-        let alphaStore:Nullable<number> = null;
-        
+        let alphaStore: Nullable<number> = null;
+
         this.pointerEnterAnimation = () => {
         this.pointerEnterAnimation = () => {
             alphaStore = this.alpha;
             alphaStore = this.alpha;
             this.alpha -= 0.1;
             this.alpha -= 0.1;

+ 4 - 2
gui/src/2D/controls/container.ts

@@ -314,14 +314,16 @@ export class Container extends Control {
             }
             }
             rebuildCount++;
             rebuildCount++;
         }
         }
-        while(this._rebuildLayout && rebuildCount < 3);
+        while (this._rebuildLayout && rebuildCount < 3);
 
 
         if (rebuildCount > 3) {
         if (rebuildCount > 3) {
             BABYLON.Tools.Error(`Layout cycle detected in GUI (Container uniqueId=${this.uniqueId})`);
             BABYLON.Tools.Error(`Layout cycle detected in GUI (Container uniqueId=${this.uniqueId})`);
         }
         }
-        
+
         context.restore();
         context.restore();
 
 
+        this._isDirty = false;
+
         return true;
         return true;
     }
     }
 
 

+ 5 - 4
gui/src/2D/controls/control.ts

@@ -43,7 +43,8 @@ export class Control {
     protected _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
     protected _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
     /** @hidden */
     /** @hidden */
     protected _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
     protected _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
-    private _isDirty = true;
+    /** @hidden */
+    protected _isDirty = true;
     /** @hidden */
     /** @hidden */
     public _tempParentMeasure = Measure.Empty();
     public _tempParentMeasure = Measure.Empty();
     /** @hidden */
     /** @hidden */
@@ -1308,7 +1309,6 @@ export class Control {
         // Do nothing
         // Do nothing
     }
     }
 
 
-
     /** @hidden */
     /** @hidden */
     protected _clipForChildren(context: CanvasRenderingContext2D): void {
     protected _clipForChildren(context: CanvasRenderingContext2D): void {
         // DO nothing
         // DO nothing
@@ -1339,6 +1339,7 @@ export class Control {
         this._clipForChildren(context);
         this._clipForChildren(context);
     }
     }
 
 
+    /** @hidden */
     public _render(context: CanvasRenderingContext2D): boolean {
     public _render(context: CanvasRenderingContext2D): boolean {
         if (!this.isVisible || this.notRenderable || this._isClipped) {
         if (!this.isVisible || this.notRenderable || this._isClipped) {
             return false;
             return false;
@@ -1354,12 +1355,12 @@ export class Control {
         if (this.clipChildren) {
         if (this.clipChildren) {
             this._clip(context);
             this._clip(context);
         }
         }
-        
+
         if (this.onBeforeDrawObservable.hasObservers()) {
         if (this.onBeforeDrawObservable.hasObservers()) {
             this.onBeforeDrawObservable.notifyObservers(this);
             this.onBeforeDrawObservable.notifyObservers(this);
         }
         }
 
 
-        this._draw(context);        
+        this._draw(context);
         this._renderHighlight(context);
         this._renderHighlight(context);
 
 
         if (this.onAfterDrawObservable.hasObservers()) {
         if (this.onAfterDrawObservable.hasObservers()) {

+ 1 - 1
gui/src/2D/controls/image.ts

@@ -347,7 +347,7 @@ export class Image extends Control {
                     break;
                     break;
             }
             }
         }
         }
-        
+
         context.restore();
         context.restore();
     }
     }
 
 

+ 4 - 4
gui/src/2D/controls/index.ts

@@ -13,13 +13,13 @@ export * from "./multiLine";
 export * from "./radioButton";
 export * from "./radioButton";
 export * from "./stackPanel";
 export * from "./stackPanel";
 export * from "./selector";
 export * from "./selector";
-export * from "./scrollViewer";
+export * from "./scrollViewers/scrollViewer";
 export * from "./textBlock";
 export * from "./textBlock";
 export * from "./virtualKeyboard";
 export * from "./virtualKeyboard";
 export * from "./rectangle";
 export * from "./rectangle";
 export * from "./displayGrid";
 export * from "./displayGrid";
-export * from "./baseSlider";
-export * from "./slider";
-export * from "./imageBasedSlider";
+export * from "./sliders/baseSlider";
+export * from "./sliders/slider";
+export * from "./sliders/imageBasedSlider";
 
 
 export * from "./statics";
 export * from "./statics";

+ 32 - 21
gui/src/2D/controls/scrollViewer.ts

@@ -1,11 +1,11 @@
-import { Rectangle } from "./rectangle";
-import { Grid } from "./grid";
-import { Control } from "./control";
-import { Slider } from "./slider";
-import { Container } from "./container";
+import { Rectangle } from "../rectangle";
+import { Grid } from "../grid";
+import { Control } from "../control";
+import { Container } from "../container";
 import { PointerInfo, Observer, Nullable } from "babylonjs";
 import { PointerInfo, Observer, Nullable } from "babylonjs";
 import { AdvancedDynamicTexture, Measure } from "2D";
 import { AdvancedDynamicTexture, Measure } from "2D";
 import { _ScrollViewerWindow } from "./scrollViewerWindow";
 import { _ScrollViewerWindow } from "./scrollViewerWindow";
+import { ScrollBar } from "../sliders/scrollBar";
 
 
 /**
 /**
  * Class used to hold a viewer window and sliders in a grid
  * Class used to hold a viewer window and sliders in a grid
@@ -14,8 +14,9 @@ export class ScrollViewer extends Rectangle {
     private _grid: Grid;
     private _grid: Grid;
     private _horizontalBarSpace: Rectangle;
     private _horizontalBarSpace: Rectangle;
     private _verticalBarSpace: Rectangle;
     private _verticalBarSpace: Rectangle;
-    private _horizontalBar: Slider;
-    private _verticalBar: Slider;
+    private _dragSpace: Rectangle;
+    private _horizontalBar: ScrollBar;
+    private _verticalBar: ScrollBar;
     private _barColor: string;
     private _barColor: string;
     private _barBorderColor: string;
     private _barBorderColor: string;
     private _barBackground: string ;
     private _barBackground: string ;
@@ -38,7 +39,7 @@ export class ScrollViewer extends Rectangle {
         if (!control) {
         if (!control) {
             return this;
             return this;
         }
         }
-            
+
         this._window.addControl(control);
         this._window.addControl(control);
 
 
         return this;
         return this;
@@ -53,14 +54,16 @@ export class ScrollViewer extends Rectangle {
         this._window.removeControl(control);
         this._window.removeControl(control);
         return this;
         return this;
     }
     }
-    
+
     /** Gets the list of children */
     /** Gets the list of children */
     public get children(): Control[] {
     public get children(): Control[] {
         return this._window.children;
         return this._window.children;
     }
     }
 
 
     public _flagDescendantsAsMatrixDirty(): void {
     public _flagDescendantsAsMatrixDirty(): void {
-        this._window._flagDescendantsAsMatrixDirty();
+        for (var child of this._children) {
+            child._markMatrixAsDirty();
+        }
     }
     }
 
 
     /**
     /**
@@ -73,6 +76,7 @@ export class ScrollViewer extends Rectangle {
         this.onDirtyObservable.add(() => {
         this.onDirtyObservable.add(() => {
             this._horizontalBarSpace.color = this.color;
             this._horizontalBarSpace.color = this.color;
             this._verticalBarSpace.color = this.color;
             this._verticalBarSpace.color = this.color;
+            this._dragSpace.color = this.color;
         });
         });
 
 
         this.onPointerEnterObservable.add(() => {
         this.onPointerEnterObservable.add(() => {
@@ -84,8 +88,8 @@ export class ScrollViewer extends Rectangle {
         });
         });
 
 
         this._grid = new Grid();
         this._grid = new Grid();
-        this._horizontalBar = new Slider();
-        this._verticalBar = new Slider();
+        this._horizontalBar = new ScrollBar();
+        this._verticalBar = new ScrollBar();
 
 
         this._window = new _ScrollViewerWindow();
         this._window = new _ScrollViewerWindow();
         this._window.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
         this._window.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
@@ -107,10 +111,8 @@ export class ScrollViewer extends Rectangle {
         this._verticalBar.maximum = 1;
         this._verticalBar.maximum = 1;
         this._verticalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         this._verticalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         this._verticalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
         this._verticalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
-        this._verticalBar.isThumbClamped = true;
         this._verticalBar.isVertical = true;
         this._verticalBar.isVertical = true;
         this._verticalBar.rotation = Math.PI;
         this._verticalBar.rotation = Math.PI;
-        this._verticalBar.displayValueBar = false;
         this._verticalBar.isVisible = false;
         this._verticalBar.isVisible = false;
 
 
         this._verticalBarSpace = new Rectangle();
         this._verticalBarSpace = new Rectangle();
@@ -132,8 +134,6 @@ export class ScrollViewer extends Rectangle {
         this._horizontalBar.maximum = 1;
         this._horizontalBar.maximum = 1;
         this._horizontalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         this._horizontalBar.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
         this._horizontalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
         this._horizontalBar.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
-        this._horizontalBar.isThumbClamped = true;
-        this._horizontalBar.displayValueBar = false;
         this._horizontalBar.isVisible = false;
         this._horizontalBar.isVisible = false;
 
 
         this._horizontalBarSpace = new Rectangle();
         this._horizontalBarSpace = new Rectangle();
@@ -147,6 +147,10 @@ export class ScrollViewer extends Rectangle {
             this._window.left = value * this._endLeft + "px";
             this._window.left = value * this._endLeft + "px";
         });
         });
 
 
+        this._dragSpace = new Rectangle();
+        this._dragSpace.thickness = 2;
+        this._grid.addControl(this._dragSpace, 1, 1);        
+
         // Colors
         // Colors
         this.barColor = "grey";
         this.barColor = "grey";
         this.barBackground = "transparent";
         this.barBackground = "transparent";
@@ -169,7 +173,7 @@ export class ScrollViewer extends Rectangle {
         this._clientWidth = this._window.parentClientWidth;
         this._clientWidth = this._window.parentClientWidth;
         this._clientHeight = this._window.parentClientHeight;
         this._clientHeight = this._window.parentClientHeight;
     }
     }
-    
+
     protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
     protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         super._additionalProcessing(parentMeasure, context);
         super._additionalProcessing(parentMeasure, context);
 
 
@@ -219,6 +223,7 @@ export class ScrollViewer extends Rectangle {
         this._barColor = color;
         this._barColor = color;
         this._horizontalBar.color = color;
         this._horizontalBar.color = color;
         this._verticalBar.color = color;
         this._verticalBar.color = color;
+        this._dragSpace.background = color;
     }
     }
 
 
     /** Gets or sets the size of the bar */
     /** Gets or sets the size of the bar */
@@ -304,6 +309,12 @@ export class ScrollViewer extends Rectangle {
         this._buildClientSizes();
         this._buildClientSizes();
         this._endLeft = this._clientWidth - windowContentsWidth;
         this._endLeft = this._clientWidth - windowContentsWidth;
         this._endTop = this._clientHeight - windowContentsHeight;
         this._endTop = this._clientHeight - windowContentsHeight;
+
+        let horizontalMultiplicator = this._clientWidth / windowContentsWidth;
+        let verticalMultiplicator = this._clientHeight / windowContentsHeight;
+
+        this._horizontalBar.thumbWidth = (this._clientWidth * horizontalMultiplicator) + "px";
+        this._verticalBar.thumbWidth = (this._clientHeight * verticalMultiplicator) + "px";
     }
     }
 
 
     public _link(host: AdvancedDynamicTexture): void {
     public _link(host: AdvancedDynamicTexture): void {
@@ -325,16 +336,16 @@ export class ScrollViewer extends Rectangle {
             }
             }
             if (this._verticalBar.isVisible == true) {
             if (this._verticalBar.isVisible == true) {
                 if ((<MouseWheelEvent>pi.event).deltaY < 0 && this._verticalBar.value > 0) {
                 if ((<MouseWheelEvent>pi.event).deltaY < 0 && this._verticalBar.value > 0) {
-                    this._verticalBar.value -= this._wheelPrecision * 100;
+                    this._verticalBar.value -= this._wheelPrecision;
                 } else if ((<MouseWheelEvent>pi.event).deltaY > 0 && this._verticalBar.value < this._verticalBar.maximum) {
                 } else if ((<MouseWheelEvent>pi.event).deltaY > 0 && this._verticalBar.value < this._verticalBar.maximum) {
-                    this._verticalBar.value += this._wheelPrecision * 100;
+                    this._verticalBar.value += this._wheelPrecision;
                 }
                 }
             }
             }
             if (this._horizontalBar.isVisible == true) {
             if (this._horizontalBar.isVisible == true) {
                 if ((<MouseWheelEvent>pi.event).deltaX < 0 && this._horizontalBar.value < this._horizontalBar.maximum) {
                 if ((<MouseWheelEvent>pi.event).deltaX < 0 && this._horizontalBar.value < this._horizontalBar.maximum) {
-                    this._horizontalBar.value += this._wheelPrecision * 100;
+                    this._horizontalBar.value += this._wheelPrecision;
                 } else if ((<MouseWheelEvent>pi.event).deltaX > 0 && this._horizontalBar.value > 0) {
                 } else if ((<MouseWheelEvent>pi.event).deltaX > 0 && this._horizontalBar.value > 0) {
-                    this._horizontalBar.value -= this._wheelPrecision * 100;
+                    this._horizontalBar.value -= this._wheelPrecision;
                 }
                 }
             }
             }
         });
         });

+ 9 - 7
gui/src/2D/controls/scrollViewerWindow.ts

@@ -1,6 +1,6 @@
-import { Measure } from "../measure";
-import { Container } from "./container";
-import { ValueAndUnit } from "../valueAndUnit";
+import { Measure } from "../../measure";
+import { Container } from "../container";
+import { ValueAndUnit } from "../../valueAndUnit";
 
 
 /**
 /**
  * Class used to hold a the container for ScrollViewer
  * Class used to hold a the container for ScrollViewer
@@ -28,8 +28,8 @@ export class _ScrollViewerWindow extends Container {
 
 
         this._measureForChildren.left = this._currentMeasure.left;
         this._measureForChildren.left = this._currentMeasure.left;
         this._measureForChildren.top = this._currentMeasure.top;
         this._measureForChildren.top = this._currentMeasure.top;
-        
-        this._measureForChildren.width = this._currentMeasure.width;       
+
+        this._measureForChildren.width = this._currentMeasure.width;
         this._measureForChildren.height = this._currentMeasure.height;
         this._measureForChildren.height = this._currentMeasure.height;
     }
     }
 
 
@@ -46,15 +46,17 @@ export class _ScrollViewerWindow extends Container {
         }
         }
 
 
         if (this._currentMeasure.width !== maxWidth) {
         if (this._currentMeasure.width !== maxWidth) {
-            this._width = new ValueAndUnit(maxWidth, ValueAndUnit.UNITMODE_PIXEL);
+            this._width.updateInPlace(maxWidth, ValueAndUnit.UNITMODE_PIXEL);
             this._currentMeasure.width = maxWidth;
             this._currentMeasure.width = maxWidth;
             this._rebuildLayout = true;
             this._rebuildLayout = true;
+            this._isDirty = true;
         }
         }
 
 
         if (this._currentMeasure.height !== maxHeight) {
         if (this._currentMeasure.height !== maxHeight) {
-            this._height = new ValueAndUnit(maxHeight, ValueAndUnit.UNITMODE_PIXEL);
+            this._height.updateInPlace(maxHeight, ValueAndUnit.UNITMODE_PIXEL);
             this._currentMeasure.height = maxHeight;
             this._currentMeasure.height = maxHeight;
             this._rebuildLayout = true;
             this._rebuildLayout = true;
+            this._isDirty = true;
         }
         }
 
 
         super._postMeasure();
         super._postMeasure();

+ 1 - 1
gui/src/2D/controls/selector.ts

@@ -4,7 +4,7 @@ import { Control } from "./control";
 import { TextBlock } from "./textBlock";
 import { TextBlock } from "./textBlock";
 import { Checkbox } from "./checkbox";
 import { Checkbox } from "./checkbox";
 import { RadioButton } from "./radioButton";
 import { RadioButton } from "./radioButton";
-import { Slider } from "./slider";
+import { Slider } from "./sliders/slider";
 import { Container } from "./container";
 import { Container } from "./container";
 
 
 /** Class used to create a RadioGroup
 /** Class used to create a RadioGroup

+ 6 - 5
gui/src/2D/controls/baseSlider.ts

@@ -1,5 +1,5 @@
-import { Control } from "./control";
-import { ValueAndUnit } from "../valueAndUnit";
+import { Control } from "../control";
+import { ValueAndUnit } from "../../valueAndUnit";
 import { Observable, Vector2 } from "babylonjs";
 import { Observable, Vector2 } from "babylonjs";
 
 
 /**
 /**
@@ -40,7 +40,7 @@ export class BaseSlider extends Control {
 
 
         this._displayThumb = value;
         this._displayThumb = value;
         this._markAsDirty();
         this._markAsDirty();
-    }  
+    }
 
 
     /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
     /** Gets or sets main bar offset (ie. the margin applied to the value bar) */
     public get barOffset(): string | number {
     public get barOffset(): string | number {
@@ -158,7 +158,7 @@ export class BaseSlider extends Control {
         this._isThumbClamped = value;
         this._isThumbClamped = value;
         this._markAsDirty();
         this._markAsDirty();
     }
     }
-
+    
     /**
     /**
      * Creates a new BaseSlider
      * Creates a new BaseSlider
      * @param name defines the control name
      * @param name defines the control name
@@ -255,7 +255,8 @@ export class BaseSlider extends Control {
     // Events
     // Events
     private _pointerIsDown = false;
     private _pointerIsDown = false;
 
 
-    private _updateValueFromPointer(x: number, y: number): void {
+    /** @hidden */
+    protected _updateValueFromPointer(x: number, y: number): void {
         if (this.rotation != 0) {
         if (this.rotation != 0) {
             this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
             this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
             x = this._transformedPosition.x;
             x = this._transformedPosition.x;

+ 6 - 2
gui/src/2D/controls/imageBasedSlider.ts

@@ -1,6 +1,6 @@
 import { BaseSlider } from "./baseSlider";
 import { BaseSlider } from "./baseSlider";
-import { Measure } from "../measure";
-import { Image } from "./image";
+import { Measure } from "../../measure";
+import { Image } from "../image";
 
 
 /**
 /**
  * Class used to create slider controls based on images
  * Class used to create slider controls based on images
@@ -122,6 +122,7 @@ export class ImageBasedSlider extends BaseSlider {
                     this._tempMeasure.width += this._effectiveThumbThickness;
                     this._tempMeasure.width += this._effectiveThumbThickness;
                 }
                 }
             }
             }
+            this._backgroundImage._currentMeasure.copyFrom(this._tempMeasure);
             this._backgroundImage._draw(context);
             this._backgroundImage._draw(context);
         }
         }
 
 
@@ -141,6 +142,7 @@ export class ImageBasedSlider extends BaseSlider {
                     this._tempMeasure.copyFromFloats(left, top, thumbPosition, height);
                     this._tempMeasure.copyFromFloats(left, top, thumbPosition, height);
                 }
                 }
             }
             }
+            this._valueBarImage._currentMeasure.copyFrom(this._tempMeasure);
             this._valueBarImage._draw(context);
             this._valueBarImage._draw(context);
         }
         }
 
 
@@ -151,6 +153,8 @@ export class ImageBasedSlider extends BaseSlider {
             } else {
             } else {
                 this._tempMeasure.copyFromFloats(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, this._effectiveThumbThickness, this._currentMeasure.height);
                 this._tempMeasure.copyFromFloats(this._currentMeasure.left + thumbPosition, this._currentMeasure.top, this._effectiveThumbThickness, this._currentMeasure.height);
             }
             }
+            
+            this._thumbImage._currentMeasure.copyFrom(this._tempMeasure);
             this._thumbImage._draw(context);
             this._thumbImage._draw(context);
         }
         }
 
 

+ 155 - 0
gui/src/2D/controls/sliders/scrollBar.ts

@@ -0,0 +1,155 @@
+import { BaseSlider } from "./baseSlider";
+import { Control } from "..";
+import { Vector2 } from "babylonjs";
+import { Measure } from "../../measure";
+
+/**
+ * Class used to create slider controls
+ */
+export class ScrollBar extends BaseSlider {
+    private _background = "black";
+    private _borderColor = "white";
+    private _thumbMeasure = new Measure(0, 0, 0, 0);
+
+    /** Gets or sets border color */
+    public get borderColor(): string {
+        return this._borderColor;
+    }
+
+    public set borderColor(value: string) {
+        if (this._borderColor === value) {
+            return;
+        }
+
+        this._borderColor = value;
+        this._markAsDirty();
+    }
+
+    /** Gets or sets background color */
+    public get background(): string {
+        return this._background;
+    }
+
+    public set background(value: string) {
+        if (this._background === value) {
+            return;
+        }
+
+        this._background = value;
+        this._markAsDirty();
+    }
+
+    /**
+     * Creates a new Slider
+     * @param name defines the control name
+     */
+    constructor(public name?: string) {
+        super(name);
+    }
+
+    protected _getTypeName(): string {
+        return "Scrollbar";
+    }
+
+    protected _getThumbThickness(): number {
+        var thumbThickness = 0;
+        if (this._thumbWidth.isPixel) {
+            thumbThickness = this._thumbWidth.getValue(this._host);
+        }
+        else {
+            thumbThickness = this._backgroundBoxThickness * this._thumbWidth.getValue(this._host);
+        }
+        return thumbThickness;
+    }
+
+    public _draw(context: CanvasRenderingContext2D): void {
+        context.save();
+
+        this._applyStates(context);
+        this._prepareRenderingData("rectangle");
+        var left = this._renderLeft;
+        var top = this._renderTop;
+        var width = this._renderWidth;
+        var height = this._renderHeight;
+
+        const thumbPosition = this._getThumbPosition();
+        context.fillStyle = this._background;
+
+        if (this.isVertical) {
+            context.fillRect(left, top, width, height + this._effectiveThumbThickness);
+        }
+        else {
+            context.fillRect(left, top, width + this._effectiveThumbThickness, height);
+        }
+
+        // Value bar
+        context.fillStyle = this.color;
+
+        // Thumb        
+        if (this.isVertical) {
+            this._thumbMeasure.left = left - this._effectiveBarOffset;
+            this._thumbMeasure.top = this._currentMeasure.top + thumbPosition;
+            this._thumbMeasure.width = this._currentMeasure.width;            
+            this._thumbMeasure.height = this._effectiveThumbThickness;
+        }
+        else {
+            this._thumbMeasure.left = this._currentMeasure.left + thumbPosition;
+            this._thumbMeasure.top = this._currentMeasure.top;
+            this._thumbMeasure.width = this._effectiveThumbThickness;
+            this._thumbMeasure.height = this._currentMeasure.height;
+        }
+        
+        context.fillRect(this._thumbMeasure.left, this._thumbMeasure.top, this._thumbMeasure.width , this._thumbMeasure.height);
+
+        context.restore();
+    }
+
+    private _first: boolean;
+    private _originX: number;
+    private _originY: number;
+
+    /** @hidden */
+    protected _updateValueFromPointer(x: number, y: number): void {
+        if (this.rotation != 0) {
+            this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
+            x = this._transformedPosition.x;
+            y = this._transformedPosition.y;
+        }
+
+        if (this._first) {
+            this._first = false;
+            this._originX = x;
+            this._originY = y;
+
+            // Check if move is required
+            if (x < this._thumbMeasure.left || x > this._thumbMeasure.left + this._thumbMeasure.width || y < this._thumbMeasure.top || y > this._thumbMeasure.top + this._thumbMeasure.height) {
+                if (this.isVertical) {
+                    this.value = this.minimum + (1 - ((y - this._currentMeasure.top) / this._currentMeasure.height)) * (this.maximum - this.minimum);
+                }
+                else {
+                    this.value = this.minimum + ((x - this._currentMeasure.left) / this._currentMeasure.width) * (this.maximum - this.minimum);
+                }
+            }
+        }
+
+        // Delta mode
+        let delta = 0;
+        if (this.isVertical) {
+            delta = -((y - this._originY) / (this._currentMeasure.height - this._effectiveThumbThickness));
+        }
+        else {
+            delta = (x - this._originX) / (this._currentMeasure.width - this._effectiveThumbThickness);
+        }
+
+        this.value += delta * (this.maximum - this.minimum);
+
+        this._originX = x;
+        this._originY = y;        
+    }
+
+    public _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean {
+        this._first = true;
+
+        return super._onPointerDown(target, coordinates, pointerId, buttonIndex);
+    }  
+}

+ 1 - 1
gui/src/2D/controls/slider.ts

@@ -21,7 +21,7 @@ export class Slider extends BaseSlider {
 
 
         this._displayValueBar = value;
         this._displayValueBar = value;
         this._markAsDirty();
         this._markAsDirty();
-    }      
+    }
 
 
     /** Gets or sets border color */
     /** Gets or sets border color */
     public get borderColor(): string {
     public get borderColor(): string {

+ 2 - 2
gui/src/2D/controls/stackPanel.ts

@@ -90,10 +90,10 @@ export class StackPanel extends Container {
                 child.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
                 child.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
             }
             }
         }
         }
- 
+
         super._preMeasure(parentMeasure, context);
         super._preMeasure(parentMeasure, context);
     }
     }
-   
+
     protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
     protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
         super._additionalProcessing(parentMeasure, context);
         super._additionalProcessing(parentMeasure, context);
 
 

+ 15 - 6
gui/src/2D/controls/textBlock.ts

@@ -230,26 +230,35 @@ export class TextBlock extends Control {
         if (!this._fontOffset) {
         if (!this._fontOffset) {
             this._fontOffset = Control._GetFontOffset(context.font);
             this._fontOffset = Control._GetFontOffset(context.font);
         }
         }
-        
+
         // Prepare lines
         // Prepare lines
         this._lines = this._breakLines(this._currentMeasure.width, context);
         this._lines = this._breakLines(this._currentMeasure.width, context);
         this.onLinesReadyObservable.notifyObservers(this);
         this.onLinesReadyObservable.notifyObservers(this);
-        
+
         let maxLineWidth: number = 0;
         let maxLineWidth: number = 0;
 
 
         for (let i = 0; i < this._lines.length; i++) {
         for (let i = 0; i < this._lines.length; i++) {
             const line = this._lines[i];
             const line = this._lines[i];
 
 
-            if (line.width > maxLineWidth) { 
-                maxLineWidth = line.width; 
+            if (line.width > maxLineWidth) {
+                maxLineWidth = line.width;
             }
             }
         }
         }
 
 
         if (this._resizeToFit) {
         if (this._resizeToFit) {
             if (this._textWrapping === TextWrapping.Clip) {
             if (this._textWrapping === TextWrapping.Clip) {
-                this.width = this.paddingLeftInPixels + this.paddingRightInPixels + maxLineWidth + 'px';
+                let newWidth = this.paddingLeftInPixels + this.paddingRightInPixels + maxLineWidth;
+                if (newWidth !== this._width.internalValue) {
+                    this._width.updateInPlace(newWidth, ValueAndUnit.UNITMODE_PIXEL);
+                    this._isDirty = true;
+                }
+            }
+            let newHeight = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length;
+
+            if (newHeight !== this._height.internalValue) {
+                this._height.updateInPlace(newHeight, ValueAndUnit.UNITMODE_PIXEL);
+                this._isDirty = true;
             }
             }
-            this.height = this.paddingTopInPixels + this.paddingBottomInPixels + this._fontOffset.height * this._lines.length + 'px';
         }
         }
 
 
         super._processMeasures(parentMeasure, context);
         super._processMeasures(parentMeasure, context);

+ 13 - 0
gui/src/2D/valueAndUnit.ts

@@ -57,6 +57,19 @@ export class ValueAndUnit {
     }
     }
 
 
     /**
     /**
+     * Update the current value and unit. This should be done cautiously as the GUi won't be marked as dirty with this function.
+     * @param value defines the value to store
+     * @param unit defines the unit to store
+     * @returns the current ValueAndUnit
+     */
+    public updateInPlace(value: number, unit = ValueAndUnit.UNITMODE_PIXEL): ValueAndUnit {
+        this._value = value;
+        this.unit = unit;
+
+        return this;
+    }
+
+    /**
      * Gets the value accordingly to its unit
      * Gets the value accordingly to its unit
      * @param host  defines the root host
      * @param host  defines the root host
      * @returns the value
      * @returns the value