PDA

View Full Version : [FIXED] Can not use IconButton in UiBinder.



Konstantin.Scheglov
16 Jan 2012, 8:15 PM
[ERROR] com.sencha.gxt.widget.core.client.button.IconButton has no default (zero args) constructor. To fix this, you can define a @UiFactory method on the UiBinder's owner, or annotate a constructor of IconButton with @UiConstructor.


May be really @UiConstructor required?

And in any case IconButton looks unfriendly for UiBinder because there are no default constructor.

Konstantin.Scheglov
10 Feb 2012, 7:36 PM
Any answer?

WesleyMoy
17 Feb 2012, 2:18 PM
The reason you're getting this error is, like you said, that IconButton doesn't have a default constructor. We've made no special provisions for IconButton in UiBinder, as it makes a lot of sense to have the icon set up when constructing the IconButton, and this is cumbersome to do in UiBinder anyway.

It's easy enough to use either a UiFactory method or a UiField for IconButton with provided=true. In either case, you will be doing the construction of the IconButton yourself in Java code.

darrellmeyer
7 Mar 2012, 10:29 AM
We have added a @UiConstructor annotation to IconButton and also added an annotation to IconConfig. Changes are in SVN and will go out in the next release.

WesleyMoy
28 Mar 2012, 3:02 PM
This enhancement has been added in the Ext GWT 3.0 Release Candidate. Please upgrade your copy of Ext GWT and try your test case again. While we're confident that we've addressed this issue, please reply if you notice any continued problems after upgrading. Again, thanks for taking the time to report this issue.

walkerr
18 Oct 2013, 3:54 AM
Old thread I know, but newbie to UiBinder and struggling to figure the right combo of XML syntax to make this work.

Anyone have a short example of usage?

walkerr
18 Oct 2013, 4:11 AM
Ok, I sort of got this working - but not sure if it's right approach:




<ui:style>
.l-btn-disconnect { background-image:url(disconnect.gif) !important; }
</ui:style>


<ui:with field='discCfg' type='com.sencha.gxt.widget.core.client.button.IconButton.IconConfig'>
<ui:attributes style="{style.l-btn-disconnect}" overStyle="{style.l-btn-disconnect}" disableStyle="{style.l-btn-disconnect}"/>
</ui:with>

...
<button:IconButton config='{discCfg}'/>
...


Seems a bit long winded, plus there only seems to be a @UIConstuctor annotation for the full 3 arg constructor and not the simple case where 1 icon should be used for all 3 cases.

Also noticed that the icon appears initially, but on first mousover when the mouse leaves it then disappears and can only be seen when mouseover again.

Maybe I'm missing the point here?

I know one option is to do all the above in Java using a @UiField(provided=true), but that seems to be going against the whole idea of separating layout into templates.

Colin Alworth
22 Oct 2013, 9:55 AM
Seems a bit long winded, plus there only seems to be a @UIConstuctor annotation for the full 3 arg constructor and not the simple case where 1 icon should be used for all 3 cases.
For better or worse, the way UiBinder is designed is that you get one constructor that can be exposed, plus getters and setters. In this case, we could have exposed a simpler constructor and allowed the (optional?) use of the setters to wire up the other settings.

That said, the style cannot be optional, and the hover style *shouldn't* be optional (note that DualListField doesn't have any), and the disabled style is likewise very handy. I'll reopen this issue to make these changes for 3.1.


Also noticed that the icon appears initially, but on first mousover when the mouse leaves it then disappears and can only be seen when mouseover again.
That definitely doesn't sound right - when the mouse leaves the button the image disappears, and won't return until you hover again? I'm be completely guessing to start speculating without a runnable sample, but will try to assemble something. I'm somewhat concerned about the !important in that style, suggesting that something else is trying to take over the styling there as well, and perhaps is succeeding.


I know one option is to do all the above in Java using a @UiField(provided=true), but that seems to be going against the whole idea of separating layout into templates.
Again, for better or worse, uibinder is somewhat limited in how complex objects can be built up, by design. For greater reuse, the IconButton/ToolButton uses predefined config objects, though developers often stick all of their configs in a single class like we do in ToolButton, and get access to them all with a ui:import statement:



<ui:import field="com.sencha.gxt.widget.core.client.button.ToolButton.*" />

<!-- ... -->
<button:ToolButton ui:field="portlet1Close" config="{CLOSE}"



If you just want a clickable icon, using the Tool/Icon button is probably overkill, since that is designed for hover styles, etc - consider just drawing that image as an Image and adding a click handler, or something similar. We generally make the tradeoff in GXT of leaving you room to grow and add complexity at the cost of taking a little longer to get it going in the first place, this situation seems to be a combination of that and the limited flexibility of UiBinder.

walkerr
22 Oct 2013, 9:30 PM
Ok, great, thanks for those tips Colin. Will take a look later on today/tomorrow. I have 3.0.6 now, so maybe that will change also.

I'm no CSS expert, and just pasted the URL links from our current CSS file. I think I tried taking the !important out and it made no difference. Will also check that too.

I did wonder if we could just put an Image in there instead, will look at that. I realised that one of the 2 buttons has a disabled state, so the IconButton is actually appropriate. I don't have a "greyed out" disabled image though, maybe there's some CSS magic that can do that automatically for me - will go Google. I definitely see some other buttons on our old panels seem to automatically dim when disabled without is providing an alternate image. Will run up Firebug and see what's going on under the hood to make that happen.

walkerr
25 Oct 2013, 12:09 AM
The attached recreates the vanishing icon case in a trivial standalone example (based on the supplied samples), also without UiBinder to test whether that was a factor.

The leftmost Image works, as does the middle TextButton. The IconButton shows an initial image, but once the first mouse over leaves the area of the button it disappears until the mouse goes over it again.

It could be worked around with an Image I guess, but this really is a button - and in other cases we need things like different disabled styles etc. So we end up adding a ton of code to Image just to make it behave like a button, which seems crazy when there is an existing class that should do this.

On a related note - what's the chance of an "auto" disabled icon i.e. if not supplied, the automatic icon for disabled is a greyed out version of the normal icon. This is very handy when you're not too fussed about the detail! I guess it could get tricky though with UIBinder, since with only 1 UIConstructor allowed we still need to specify the style explicitly. It's very useful to not always have to worry about the disabled styles tho.

walkerr
25 Oct 2013, 2:08 AM
On a related note - what's the chance of an "auto" disabled icon i.e. if not supplied, the automatic icon for disabled is a greyed out version of the normal icon. This is very handy when you're not too fussed about the detail!

Cancel that last bit (above) - I tried the automatic disabled case:



IconConfig cfg2 = new IconConfig("l-btn-refresh");
IconButton btn2 = new IconButton(cfg2);
btn2.setEnabled(false);
cp.addTool(btn2);


The button is "dimmed" in an acceptable way when being lazy and not wanting to create separate styles, plus the mouse-hover cursor is also changed to not show the "hand" indicating clickable. So spot on really for the basic case.

Note though - this now makes me want the convenience of the single-arg UIConstructor version in UiBinder even more!

Would still really like to get to the bottom of the vanishing icons though - with that solved, this will be a good approach for us.

One thing I do notice with the above - is that the vanishing icon does not happen in the simple single-arg case. Makes me wonder if it's something to do with the 3-arg constructor:



public IconButton.IconConfig(String style,
String overStyle,
String disableStyle)


Maybe that explicit middle "overStyle" arg is in some way causing the style to get removed when the mouse leaves?


Inspired by that thought, I expanded the example:



IconConfig cfg1 = new IconConfig("l-btn-refresh", "l-btn-refresh", "l-btn-refresh");
IconButton btn1 = new IconButton(cfg1);
cp.addTool(btn1);

IconConfig cfg2 = new IconConfig("l-btn-refresh");
IconButton btn2 = new IconButton(cfg2);
btn2.setEnabled(false);
cp.addTool(btn2);


IconConfig cfg3 = new IconConfig("l-btn-refresh");
IconButton btn3 = new IconButton(cfg3);
cp.addTool(btn3);

IconConfig cfg4 = new IconConfig("l-btn-refresh", "l-btn-refreshDisabled", "l-btn-refreshOver");
IconButton btn4 = new IconButton(cfg4);
cp.addTool(btn4);

IconConfig cfg5 = new IconConfig("l-btn-refresh", "l-btn-refreshDisabled", "l-btn-refreshOver");
IconButton btn5 = new IconButton(cfg5);
btn5.setEnabled(false);
cp.addTool(btn5);


"btn2" is the only one that exhibits the vanishing icon scenario

"btn3" shows a dimmed icon and is disabled. Using F12 Explorer, I figured what was happening here - it acquires an auto style:

46559

So I took a punt and added *Disabled and *Over to the explicit constructors.

"btn4" is enabled, and the seems to work without any vanishing icon

"btn5" shows the same disabled as a dimmer icon version, and also doesn't show the vanishing icon.

Going back to the original UiBinder case though, the above workaround needs some modification to make it usable. GWT does not like a missing inline style, so the disabled and over styles have to be made non-existent top level styles:



<ui:with field='refreshCfg' type='com.sencha.gxt.widget.core.client.button.IconButton.IconConfig'>
<!-- doesn't work, generates GWT errors because the inline style does not exist
<ui:attributes style="{style.l-btn-refresh}" overStyle="{style.l-btn-refreshOver}" disableStyle="{style.l-btn-refreshDisabled}"/>
-->
<!-- works -->
<ui:attributes style="{style.l-btn-refresh}" overStyle="l-btn-refreshOver" disableStyle="l-btn-refreshDisabled"/>
</ui:with>


So in one sense, a decent result to find a workaround. It feels clunky though - the single-arg constructor case would be much better!