diff --git a/src/ru/stablex/ui/UIBuilder.hx b/src/ru/stablex/ui/UIBuilder.hx index 27e594a..fa03cdd 100644 --- a/src/ru/stablex/ui/UIBuilder.hx +++ b/src/ru/stablex/ui/UIBuilder.hx @@ -605,9 +605,9 @@ class UIBuilder { } if( cls != null ){ - if( UIBuilder._imports.exists(cls) ) Err.trigger('Class is already imported: ' + cls); - UIBuilder._imports.set(cls, fullyQualifiedName); - + if( !UIBuilder._imports.exists(cls) ){ // Err.trigger('Class is already imported: ' + cls); + UIBuilder._imports.set(cls, fullyQualifiedName); + } }else{ Err.trigger('Wrong class name: ' + fullyQualifiedName); } diff --git a/src/ru/stablex/ui/widgets/Bmp.hx b/src/ru/stablex/ui/widgets/Bmp.hx index b568f22..b853a13 100644 --- a/src/ru/stablex/ui/widgets/Bmp.hx +++ b/src/ru/stablex/ui/widgets/Bmp.hx @@ -163,7 +163,7 @@ class Bmp extends Widget{ * Setter src * */ - private inline function set_src(src:String) : String { + private function set_src(src:String) : String { if( src != null ){ this._bitmapData = null; } diff --git a/src/ru/stablex/ui/widgets/Box.hx b/src/ru/stablex/ui/widgets/Box.hx index fb86e70..c34b4fb 100644 --- a/src/ru/stablex/ui/widgets/Box.hx +++ b/src/ru/stablex/ui/widgets/Box.hx @@ -57,10 +57,10 @@ class Box extends Widget{ * get object width * */ - @:noCompletion static private inline function _objWidth (obj:DisplayObject) : Float { + @:noCompletion static private function _objWidth (obj:DisplayObject, ignoreRot:Bool=false) : Float { // #if html5 if( Std.is(obj, Widget) ){ - return cast(obj, Widget).w; + return cast(obj, Widget).get_rotated_w() * cast(obj, Widget).scaleX; }else if( Std.is(obj, flash.text.TextField) ){ return cast(obj, flash.text.TextField).textWidth + 4; }else{ @@ -76,10 +76,10 @@ class Box extends Widget{ * get object height * */ - @:noCompletion static private inline function _objHeight (obj:DisplayObject) : Float { + @:noCompletion static private function _objHeight (obj:DisplayObject, ignoreRot:Bool=false) : Float { // #if html5 if( Std.is(obj, Widget) ){ - return cast(obj, Widget).h; + return cast(obj, Widget).get_rotated_h() * cast(obj, Widget).scaleY; }else if( Std.is(obj, flash.text.TextField) ){ return cast(obj, flash.text.TextField).textHeight + 4; }else{ @@ -126,29 +126,38 @@ class Box extends Widget{ *******************************************************************************/ + override public function onCreate() : Void { + super.onCreate(); + //trace("onCreate Box - " + name); + alignElements(); + } + /** * Refresh widgets. Re-apply skin box and realigns children * */ override public function refresh() : Void { + //trace("Box starting refresh - " + name); if( this.autoWidth || this.autoHeight ){ var w : Float = (this.autoWidth ? this._calcWidth() : this._width); var h : Float = (this.autoHeight ? this._calcHeight() : this._height); if( this._width != w || this._height != h ){ - this._width = w; this._height = h; - this.dispatchEvent(new WidgetEvent(WidgetEvent.RESIZE)); + _onResize(); + //this.dispatchEvent(new WidgetEvent(WidgetEvent.RESIZE)); } }//if( autoSize ) super.refresh(); - if( this.layout == null ){ + if ( this.layout == null ) { + //trace(" Box align in refresh"); this.alignElements(); } + //trace("Box ending refresh"); }//function refresh() @@ -165,7 +174,6 @@ class Box extends Widget{ var childW : Float = 0; for(i in 0...this.numChildren){ - child = this.getChildAt(i); child = this.getChildAt(i); if( child.visible ){ childW = Box._objWidth(child); @@ -244,6 +252,7 @@ class Box extends Widget{ * */ public function alignElements () : Void { + //trace(" in align - " + name); if( this.unifyChildren ){ this._unifyChildren(); } @@ -317,6 +326,7 @@ class Box extends Widget{ * */ @:noCompletion private function _vAlignTop () : Void { + //trace(" align top - " + name); //vertical box if( this.vertical ){ var lastY : Float = this.paddingTop; @@ -343,6 +353,7 @@ class Box extends Widget{ * */ @:noCompletion private function _vAlignMiddle () : Void { + //trace(" align middle - " + name); //vertical box if(this.vertical){ //count sum children height @@ -386,6 +397,7 @@ class Box extends Widget{ * */ @:noCompletion private function _vAlignBottom () : Void { + //trace(" align bottom - " + name); //vertical box if( this.vertical ){ var lastY : Float = this.h - this.paddingBottom; @@ -414,6 +426,7 @@ class Box extends Widget{ * */ @:noCompletion private function _hAlignLeft () : Void { + //trace(" align left - " + name); //vertical box if(this.vertical){ for(i in 0...this.numChildren){ @@ -440,6 +453,7 @@ class Box extends Widget{ * */ @:noCompletion private function _hAlignRight () : Void { + //trace(" align right - " + name); //vertical box if(this.vertical){ var child : DisplayObject; @@ -468,6 +482,7 @@ class Box extends Widget{ * */ @:noCompletion private function _hAlignCenter () : Void { + //trace(" align center - " + name); //vertical box if(this.vertical){ var child : DisplayObject; @@ -567,6 +582,7 @@ class Box extends Widget{ * */ @:noCompletion private function _onChildResize (e:WidgetEvent = null) : Void { + //trace("resized child of " + name); if( this.created ){ if( this.autoWidth || this.autoHeight ){ if( e != null ){ @@ -575,7 +591,8 @@ class Box extends Widget{ child != null && child.visible != false && !(this.autoWidth && child._widthUsePercent) && !(this.autoHeight && child._heightUsePercent) - ){ + ) { + //trace(" child is " + child.name); this.refresh(); } }else{ diff --git a/src/ru/stablex/ui/widgets/Widget.hx b/src/ru/stablex/ui/widgets/Widget.hx index 99d41f8..5cd09e3 100644 --- a/src/ru/stablex/ui/widgets/Widget.hx +++ b/src/ru/stablex/ui/widgets/Widget.hx @@ -3,6 +3,7 @@ package ru.stablex.ui.widgets; import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; +import flash.geom.Matrix; import flash.geom.Rectangle; import ru.stablex.TweenSprite; import ru.stablex.ui.events.WidgetEvent; @@ -30,7 +31,15 @@ class Widget extends TweenSprite{ @:noCompletion static private inline var _Y_USE_BOTTOM = 7; @:noCompletion static private inline var _Y_USE_BOTTOM_PERCENT = 8; + @:noCompletion static private inline var _X_REG_LEFT = 9; + @:noCompletion static private inline var _X_REG_CENTER = 10; + @:noCompletion static private inline var _X_REG_RIGHT = 11; + @:noCompletion static private inline var _Y_REG_TOP = 12; + @:noCompletion static private inline var _Y_REG_MIDDLE = 13; + @:noCompletion static private inline var _Y_REG_BOTTOM = 14; + + //Name of section in default settings for this type of widgets public var defaults : String = 'Default'; @@ -83,6 +92,21 @@ class Widget extends TweenSprite{ @:noCompletion private var _xUse : Int = _X_USE_LEFT; @:noCompletion private var _yUse : Int = _Y_USE_TOP; + // registration of widget + /** + * This should be like 'left,top' or 'bottom' or 'center,middle' etc. + * Vertical: left, right, center. Horizontal: top, bottom, middle. + * Default is 'left,top' and any unrecognized string reverts to this. + */ + public var registration (default, set_registration): String = 'left,top'; + + // rotation + public var rotate (get_rotate, set_rotate): Float; + + //Wich one to use: left, right, center, etc. + @:noCompletion private var _xReg : Int = _X_USE_LEFT; + @:noCompletion private var _yReg : Int = _Y_USE_TOP; + //Get parent if it is widget, returns null otherwise public var wparent (get_wparent,never) : Widget; @@ -261,25 +285,7 @@ class Widget extends TweenSprite{ ); } - //positioning { - switch ( this._xUse ) { - //by right border - case _X_USE_RIGHT: this.x = newParent._width - this._right - this._width; - //by right percent - case _X_USE_RIGHT_PERCENT: this.x = newParent._width - newParent._width * this._rightPercent / 100 - this._width; - //by left percent - case _X_USE_LEFT_PERCENT: this.x = newParent._width * this._leftPercent / 100; - }//switch() - - switch ( this._yUse ) { - //by bottom border - case _Y_USE_BOTTOM: this.y = newParent._height - this._bottom - this._height; - //by bottom percent - case _Y_USE_BOTTOM_PERCENT: this.y = newParent._height - newParent._height * this._bottomPercent / 100 - this._height; - //by top percent - case _Y_USE_TOP_PERCENT: this.y = newParent._height * this._topPercent / 100; - }//switch() - //} + _do_positioning(newParent); //notify UIBuilder.dispatcher.dispatchEvent(new WidgetEvent( WidgetEvent.ADDED, this )); @@ -302,25 +308,7 @@ class Widget extends TweenSprite{ ); } - //positioning { - switch ( this._xUse ) { - //by right border - case _X_USE_RIGHT: this.x = parent._width - this._right - this._width; - //by right percent - case _X_USE_RIGHT_PERCENT: this.x = parent._width - parent._width * this._rightPercent / 100 - this.w; - //by left percent - case _X_USE_LEFT_PERCENT: this.x = parent._width * this._leftPercent / 100; - }//switch() - - switch ( this._yUse ) { - //by bottom border - case _Y_USE_BOTTOM: this.y = parent._height - this._bottom - this._height; - //by bottom percent - case _Y_USE_BOTTOM_PERCENT: this.y = parent._height - parent._height * this._bottomPercent / 100 - this._height; - //by top percent - case _Y_USE_TOP_PERCENT: this.y = parent._height * this._topPercent / 100; - }//switch() - //} + _do_positioning(parent); }//function _onParentResize() @@ -342,6 +330,78 @@ class Widget extends TweenSprite{ this._onResize(); }//function resize() + @:final @:noCompletion private function _do_positioning( myParent:Widget ) : Void { + switch( this._xUse ) { + //by left border + case _X_USE_LEFT: this.x = this._left + _xRegCorrection(_X_USE_LEFT); + //by left percent + case _X_USE_LEFT_PERCENT: this.x = (myParent._width * this._leftPercent / 100) + _xRegCorrection(_X_USE_LEFT); + //by right border + case _X_USE_RIGHT: this.x = (myParent._width - this._right - this.get_rotated_w()) + _xRegCorrection(_X_USE_RIGHT); + //by right percent + case _X_USE_RIGHT_PERCENT: this.x = ((myParent._width * ((100 - this._rightPercent) / 100)) - this.get_rotated_w()) + _xRegCorrection(_X_USE_RIGHT); + }//switch() + + switch ( this._yUse ) { + //by top border + case _Y_USE_TOP: this.y = this._top + _yRegCorrection(_Y_USE_TOP); + //by top percent + case _Y_USE_TOP_PERCENT: this.y = (myParent._height * this._topPercent / 100) + _yRegCorrection(_Y_USE_TOP); + //by bottom border + case _Y_USE_BOTTOM: this.y = (myParent._height - this._bottom - this.get_rotated_h()) + _yRegCorrection(_Y_USE_BOTTOM); + //by bottom percent + case _Y_USE_BOTTOM_PERCENT: this.y = ((myParent._height * ((100 - this._bottomPercent) / 100)) - this.get_rotated_h()) + _yRegCorrection(_Y_USE_BOTTOM); + }//switch() + } + + @:final @:noCompletion private function _xRegCorrection ( xUse:Int ) : Float + { + if ( (xUse == _X_USE_RIGHT) || (xUse == _X_USE_RIGHT_PERCENT) ) + { + switch ( this._xReg ) + { + case _X_REG_LEFT: return this.get_rotated_w() * this.scaleX; + //case _X_REG_RIGHT: return 0; + case _X_REG_CENTER: return (this.get_rotated_w() / 2) * this.scaleX; + } + } + else // assume LEFT + { + switch ( this._xReg ) + { + //case _X_REG_LEFT: return 0; + case _X_REG_RIGHT: return -this.get_rotated_w() * this.scaleX; + case _X_REG_CENTER: return -(this.get_rotated_w() / 2) * this.scaleX; + } + } + + return 0; + } + + @:final @:noCompletion private function _yRegCorrection ( yUse:Int ) : Float + { + if ( (yUse == _Y_USE_BOTTOM) || (yUse == _Y_USE_BOTTOM_PERCENT) ) + { + switch ( this._yReg ) + { + case _Y_REG_TOP: return this.get_rotated_h() * this.scaleY; + //case _Y_REG_BOTTOM: return 0; + case _Y_REG_MIDDLE: return (this.get_rotated_h() / 2) * this.scaleY; + } + } + else // assume TOP + { + switch ( this._yReg ) + { + //case _Y_REG_TOP: return 0; + case _Y_REG_BOTTOM: return -this.get_rotated_h() * this.scaleY; + case _Y_REG_MIDDLE: return -(this.get_rotated_h() / 2) * this.scaleY; + } + } + + return 0; + } + /** * Called every time this object is resized. This methods calls `.refresh()` and `.onResize()` wich @@ -352,20 +412,8 @@ class Widget extends TweenSprite{ */ @:final @:noCompletion private function _onResize() : Void { //positioning - if( this.wparent != null ){ - switch( this._xUse ){ - //by right border - case _X_USE_RIGHT: this.x = this.wparent._width - this._right - this._width; - //by right percent - case _X_USE_RIGHT_PERCENT: this.x = this.wparent._width - this.wparent._width * this._rightPercent / 100 - this._width; - }//switch() - - switch ( this._yUse ) { - //by bottom border - case _Y_USE_BOTTOM: this.y = this.wparent._height - this._bottom - this._height; - //by bottom percent - case _Y_USE_BOTTOM_PERCENT: this.y = this.wparent._height - this.wparent._height * this._bottomPercent / 100 - this._height; - }//switch() + if ( this.wparent != null ) { + _do_positioning(this.wparent); }//if() //handle overflow visibility @@ -601,7 +649,7 @@ class Widget extends TweenSprite{ */ @:noCompletion private function set_left(l:Float) : Float { this._xUse = _X_USE_LEFT; - this.x = l; + this.x = l + _xRegCorrection(this._xUse); return this._left = l; }//function set_left() @@ -622,7 +670,7 @@ class Widget extends TweenSprite{ @:noCompletion private function set_right(r:Float) : Float { this._xUse = _X_USE_RIGHT; if( this.wparent != null ){ - this.x = this.wparent._width - r - this.w; + this.x = this.wparent._width - r - this.w + _xRegCorrection(this._xUse); } return this._right = r; }//function set_right() @@ -653,7 +701,7 @@ class Widget extends TweenSprite{ this._xUse = _X_USE_LEFT_PERCENT; if( this.wparent != null ){ - this.x = this.wparent._width * lp / 100; + this.x = (this.wparent._width * lp / 100) + _xRegCorrection(this._xUse); } return this._leftPercent = lp; @@ -685,7 +733,7 @@ class Widget extends TweenSprite{ this._xUse = _X_USE_RIGHT_PERCENT; if( this.wparent != null ){ - this.x = this.wparent._width - this.wparent._width * rp / 100 - this.w; + this.x = (this.wparent._width - this.wparent._width * rp / 100 - this.w) + _xRegCorrection(this._xUse); } return this._rightPercent = rp; @@ -715,7 +763,7 @@ class Widget extends TweenSprite{ */ @:noCompletion private function set_top(t:Float) : Float { this._yUse = _Y_USE_TOP; - this.y = t; + this.y = t + _yRegCorrection(this._yUse); return this._top = t; }//function set_top() @@ -736,7 +784,7 @@ class Widget extends TweenSprite{ @:noCompletion private function set_bottom(b:Float) : Float { this._yUse = _Y_USE_BOTTOM; if( this.wparent != null ){ - this.y = this.wparent._height - b - this.h; + this.y = (this.wparent._height - b - this.h) + _yRegCorrection(this._yUse); } return this._bottom = b; }//function set_bottom() @@ -767,7 +815,7 @@ class Widget extends TweenSprite{ this._yUse = _Y_USE_TOP_PERCENT; if( this.wparent != null ){ - this.y = this.wparent._height * tp / 100; + this.y = (this.wparent._height * tp / 100) + _yRegCorrection(this._yUse); } return this._topPercent = tp; @@ -799,7 +847,7 @@ class Widget extends TweenSprite{ this._yUse = _Y_USE_BOTTOM_PERCENT; if( this.wparent != null ){ - this.y = this.wparent._height - this.wparent._height * bp / 100 - this.h; + this.y = (this.wparent._height - this.wparent._height * bp / 100 - this.h) + _yRegCorrection(this._yUse); } return this._bottomPercent = bp; @@ -846,6 +894,16 @@ class Widget extends TweenSprite{ }//function get_w() + /** + * Rotated Width getter + * + */ + @:noCompletion private function get_rotated_w() : Float { + var rads:Float = Math.PI / 180 * this.rotation; + return (Math.sin(rads) * -this._height) + (Math.cos(rads) * this._width); + }//function get_rotated_w() + + /** * Height setter * @@ -869,6 +927,16 @@ class Widget extends TweenSprite{ }//function get_h() + /** + * Rotated Height getter + * + */ + @:noCompletion private function get_rotated_h() : Float { + var rads:Float = Math.PI / 180 * this.rotation; + return (Math.sin(rads) * this._width) + (Math.cos(rads) * this._height); + }//function get_rotated_h() + + /** * Width percent setter * @@ -975,5 +1043,75 @@ class Widget extends TweenSprite{ tip.bindTo(this); return this.tip = tip; }//function set_tip() - + + /** + * Registration setter + * + */ + @:final @:noCompletion private function set_registration (regs:String) : String { + var registrations : Array = regs.split(','); + + this._yReg = _Y_REG_TOP; + this._xReg = _X_REG_LEFT; + + for(reg in registrations){ + switch(reg){ + case 'top' : this._yReg = _Y_REG_TOP; + case 'middle' : this._yReg = _Y_REG_MIDDLE; + case 'bottom' : this._yReg = _Y_REG_BOTTOM; + case 'left' : this._xReg = _X_REG_LEFT; + case 'center' : this._xReg = _X_REG_CENTER; + case 'right' : this._xReg = _X_REG_RIGHT; + } + } + + registration = (switch(this._xReg) { + case _X_REG_LEFT : 'left'; + case _X_REG_CENTER : 'center'; + case _X_REG_RIGHT : 'right'; + default : 'left'; + }) + ',' + (switch(this._yReg) { + case _Y_REG_TOP : 'top'; + case _Y_REG_MIDDLE : 'middle'; + case _Y_REG_BOTTOM : 'bottom'; + default : 'top'; + }); + + return registration; + } + + @:final @:noCompletion private function set_rotate ( rot: Float ) : Float + { + this.rotation = rot; + + if ( this.wparent != null ) + { + _do_positioning(this.wparent); + } + + return this.rotation; + } + + @:final @:noCompletion private function get_rotate ( ) : Float + { + return this.rotation; + } + + public function x_relativeTo ( p_widget:Widget ) : Float + { + return this.x + ( ( (this.wparent != null) && (this.wparent != p_widget) ) ? + this.wparent.x_relativeTo(p_widget) : 0 ); + } + + public function y_relativeTo ( p_widget:Widget ) : Float + { + return this.y + ( ( (this.wparent != null) && (this.wparent != p_widget) ) ? + this.wparent.y_relativeTo(p_widget) : 0 ); + } + + public function rotation_relativeTo ( p_widget:Widget ) : Float + { + return this.rotate + ( ( (this.wparent != null) && (this.wparent != p_widget) ) ? + this.wparent.rotation_relativeTo(p_widget) : 0 ); + } }//class Widget \ No newline at end of file