RealyUniqueName / StablexUI

UI engine for Haxe OpenFL designed to give as much freedom as possible in customizing UI
http://ui.stablex.ru/doc
Other
337 stars 80 forks source link

How to set defaults from code? #81

Closed hopewise closed 10 years ago

hopewise commented 10 years ago

Settings defaults from XML works fine, it will read properties fine, but setting defaults in code has not effect ..

Please see here https://gist.github.com/hopewise/7384868

Thanks

arsfeld commented 10 years ago

Defaults are parsed in the UIBuilder (either compile-time or runtime, depending on your use of it). So when you use your widget as in your gist, you are not using UIBuilder and defaults are never parsed nor applied.

You have a few alternatives. The best one, if you don't want to use XML, is to use UIBuilder's create method (check the documentation here: http://ui.stablex.ru/doc/#ru/stablex/ui/UIBuilder.html or the code in https://github.com/RealyUniqueName/StablexUI/blob/master/src/ru/stablex/ui/UIBuilder.hx#L794)

hopewise commented 10 years ago

So this suppose to solve my issue:

static inline public function applyDefaults(obj:Widget)

I will check and reply ..

hopewise commented 10 years ago

I tried this: UIBuilder.applyDefaults(this); The buttons will look as hoovered, when I move the mouse over them and mouse out, text and color will look correct .. I think applyDefaults should do the job .. I will try create ..

hopewise commented 10 years ago

I tried create, but I got this error:

TypeError: Error #2007: Parameter text must be non-null. at flash.text::TextField/set text() at ru.stablex.ui.widgets::Text/set_text()[C:\Motion-Twin\haxe\lib\stablexui\1,0,11\ru\stablex\ui\widgets\Text.hx:145] at com.clientside.ui.btns::Button()[C:\xampp\htdocs\dcaclab_html5\client\src\com\clientside\ui\btns\Button.hx:23] at Type$/createInstance()[C:\HaxeToolkit\haxe\std\flash_std\Type.hx:132] at ru.stablex.ui::UIBuilder$/create()[C:\Motion-Twin\haxe\lib\stablexui\1,0,11\ru\stablex\ui\UIBuilder.hx:796] at com.clientside.main::ComponentsPanel()[C:\xampp\htdocs\dcaclab_html5\client\src\com\clientside\main\ComponentsPanel.hx:192] at com.clientside.board::Board()[C:\xampp\htdocs\dcaclab_html5\client\src\com\clientside\board\Board.hx:272] at MethodInfo-152()[C:\xampp\htdocs\dcaclab_html5\client\src\com\clientside\main\Main.hx:265] at MethodInfo-2572()[C:\Motion-Twin\haxe\lib\swf\1,1,1\format\swf\library\SWFLibrary.hx:108]

My implementation:

var multimeterBtn:Button = UIBuilder.create(Button, {text:"'Multi-Meter'" } );

I also tried:

var multimeterBtn:Button = UIBuilder.create(Button, {text:"Multi-Meter" } );

Any idea please?

arsfeld commented 10 years ago

You don't really need create if applyDefaults work for you.

The reason it's failing, I think, is because your new constructor is being called with null parameters, so aCaption is null and you are assigning it to text, which can't be null. Either set a default for aCaption (check aCaption for null and assign "" if it's null), which just creates a Button with no text which is then overridden with text from create. Or use only applyDefaults, which means you'll create the Button instance yourself and you won't have that crash.

hopewise commented 10 years ago

Thanks, I did't notice that aCaption was null, I set a default value for it and its working ..

The only thing worked for me is create, like this:

var multimeterBtn:Button = UIBuilder.create(Button, {text:"Multi-Meter", heightPt: 100, w: Utils.DPS(70)} );

Although defaults has been applied, but I have to define heightPt& w in create props, I tried to remove them and put them in my class like:

UIBuilder.apply(this, { heightPt: 100, w: Utils.DPS(70)} );

But, didn't work ..

Really thanks for your time : )

RealyUniqueName commented 10 years ago

Widgets are not supposed to be created directly via new. This is also not a good idea to override constructor. The best way is to use UIBuilder.create(WidgetClass, properties). Here is what happens under the hood of that method:

  1. Create widget with Type.createInstance(WidgetClass, []);
  2. Apply defaults via UIBuilder.applyDefaults()
  3. Apply properties provided in UIBuilder.create(WidgetClass, properties) call;
  4. Call widget.onInitialize(). This is the method you should override instead of constructor
  5. Create children if provided in properties object.
  6. Call widget.onCreate(). You can also override this method.
  7. Return created widget.

And why do you use UIBuilder.apply() if you can set properties directly and type-safe?

this.heightPt = 100;
this.w = Utils.DPS(70);
hopewise commented 10 years ago

Thanks for explanation, at last, UIBuilder.applyDefaults(this); worked as expected:

override public function onCreate():Void

{ super.onCreate(); this.defaults = "Default,OnOf"; UIBuilder.applyDefaults(this); }

Now, I don't have to set:

this.heightPt = 100; this.w = Utils.DPS(70);

because defaults are working :)

I needed to override Button, because I will be using icons created from swf library with dps scale, I thought I will have more control in a class, but yea, it can be done all in XML ...

Thanks very much for help!

On Sat, Nov 9, 2013 at 9:01 PM, RealyUniqueName notifications@github.comwrote:

Widgets are not supposed to be created directly via new. This is also not a good idea to override constructor. The best way is to use UIBuilder.create(WidgetClass, properties). Here is what happens under the hood of that method:

  1. Create widget with Type.createInstance(WidgetClass, []);
  2. Apply defaults via UIBuilder.applyDefaults()
  3. Apply properties provided in UIBuilder.create(WidgetClass, properties)call;
  4. Call widget.onInitialize(). This is the method you should override instead of constructor
  5. Create children if provided in properties object.
  6. Call widget.onCreate(). You can also override this method.
  7. Return created widget.

And why do you use UIBuilder.apply() if you can set properties directly and type-safe?

this.heightPt = 100; this.w = Utils.DPS(70);

— Reply to this email directly or view it on GitHubhttps://github.com/RealyUniqueName/StablexUI/issues/81#issuecomment-28132884 .

Kind Regards,

Samir Sabri Software Architect& Developer www.dcaclab.com Jordan-Middle East

hopewise commented 10 years ago

As this issue is not closed yet, how to align icon over button text, so that text appears under the icon?

I saw icoBeforeLabel , and I know I have to use align, but I am sorry, I couldn't get the result I want ..

RealyUniqueName commented 10 years ago

You also need to set button.vertical = true

RealyUniqueName commented 10 years ago

Oh, and you still can override constructor, but keep it without input parameters and only if you really need it

RealyUniqueName commented 10 years ago

I don't know how swf library works, but if it can produce BitmapData you don't need to override button. You can create method which will return Bmp widget with your icon drawn on it:

class Icon {
    static public function create(iconId:String) : ru.stablex.ui.widgets.Bmp {
        var bmpData : BitmapData = ...; //create BitmapData from SWF
        return UIBuilder.create(Bmp, {
            bitmapData : bmpData
        });
    }
}

Or if SWF library gives you any display object, you can attach it to Bmp widget:

class Icon {
    static public function create(iconId:String) : ru.stablex.ui.widgets.Bmp {
        var icon = ...; //create display object from SWF

        var bmp : Bmp = UIBuilder.create(Bmp, {
            w : icon.width,
            h : icon.height
        });
        bmp.addChild(icon);

        return bmp;
    }
}

And then use this method to set button's icon:

<Button ico="$Icon.create('myIconId')" text="'Hit me'"/>

or

var button = UIBuilder.create(Button, {
    ico : Icon.create('myIconId'),
    text : 'Hit me'
});
hopewise commented 10 years ago

Quite informative, I recommend to add "You also need to set button.vertical = true" in Button documentation, at "icoBeforeLabel"

RealyUniqueName commented 10 years ago

Done. Thanks for a tip )

hopewise commented 10 years ago

You're most welcome : ) On Nov 10, 2013 2:20 PM, "RealyUniqueName" notifications@github.com wrote:

Done. Thanks for a tip )

— Reply to this email directly or view it on GitHubhttps://github.com/RealyUniqueName/StablexUI/issues/81#issuecomment-28149355 .

hopewise commented 10 years ago

When I use:

<Button ico="$Icon.create('iconV')" text="'Hit me'"/> 

I get:

C:\Motion-Twin\haxe\lib/stablexui/1,0,11/ru/stablex/Err.hx:18: Class is not imported: Icon

But, if I remove "$" it works normally, so why should I add "$" to class name?

RealyUniqueName commented 10 years ago

Let's say, you have my.app.pack.Icon then you have to type this long package every time you want to use this class in xml.

<Button ico="my.app.pack.Icon.create('iconV')" icoPressed="my.app.pack.Icon.create('iconP')" text="'Hit me'"/> 
<Button ico="my.app.pack.Icon.create('iconV')" icoPressed="my.app.pack.Icon.create('iconP')" text="'Hit me'"/> 

Or you can type UIBuilder.regClass('my.app.pack.Icon') once before StablexUI initialization and reference your class as $Icon in xml.

<Button ico="$Icon.create('iconV')" icoPressed="$Icon.create('iconP')" text="'Hit me'"/> 
<Button ico="$Icon.create('iconV')" icoPressed="$Icon.create('iconP')" text="'Hit me'"/> 

But in your case Icon is in top level package, so this is not neccessary.

hopewise commented 10 years ago

Wow, didn't know that .. very cool, I will show you my app when its done ;) On Nov 11, 2013 7:40 AM, "RealyUniqueName" notifications@github.com wrote:

Let's say, you have my.app.pack.Icon then you have to type this long package every time you want to use this class in xml.