Setting className in UiBinder

95 views
Skip to first unread message

Geoff Huenemann

unread,
Mar 23, 2015, 8:48:43 PM3/23/15
to lib-g...@googlegroups.com
We have successfully ported to your gwt 2.7 version of lib-gwt-svg, and it is mostly working well.

However, I'm now trying to simplify the way we style SVG icons, and I'd like to just out the style directly in the UiBinder XML file.  I sort of expected to be able to use styleName='{style.myStyle}' like I would with any other UiBinder element, but this throws a MISSING_ELEMENT_ERROR.  After some reading, it appears that the difference in the SVG DOM means that no, I should be using classNameBaseVal instead.  Based on some examples, I tried this:

    <ui:style> 
.searchButton { float: left; padding-left: 10px; width: 25px; height: 25px; }
    </ui:style>

...

    <svg:SVGImage ui:field='searchButton' resource='{res.glass}' classNameBaseVal='{style.searchButton}' />

Although is compiles fine, I get a runtime error during initialization:

com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot read property 'setClassNameBaseVal_2_g$' of undefined
Unknown.setClassNameBaseVal_1_g$(richclient-0.js@23:375548)
Unknown.build_searchButton_0_g$(richclient-0.js@21:163294)
Unknown.get_searchButton_0_g$(richclient-0.js@15:163427)
Unknown.build_searchButtonContainer_0_g$(richclient-0.js@46:163304)
Unknown.get_searchButtonContainer_0_g$(richclient-0.js@15:163432)
Unknown.build_f_FlowPanel1_4_g$(richclient-0.js@37:163174)
Unknown.get_f_FlowPanel1_4_g$(richclient-0.js@15:163367)
Unknown.build_searchHeader_0_g$(richclient-0.js@37:163325)
Unknown.get_searchHeader_0_g$(richclient-0.js@15:163442)
Unknown.build_drawer_0_g$(richclient-0.js@31:163163)
Unknown.get_drawer_0_g$(richclient-0.js@15:163362)
Unknown.createAndBindUi_8_g$(richclient-0.js@71:163124)
Unknown.createAndBindUi_9_g$(richclient-0.js@15:163128)
Unknown.FilterHeader_1_g$(richclient-0.js@53:162844)
Unknown.$init_2061_g$(richclient-0.js@28:149330)

If I remove the classNameBaseVall property, it works fine.  If I wrap it in a SimplePanel and use styleName='{style.searchButton}' it also works fine, but the code is needlessly complicated.

I have tried many variations on this code with no luck, including a straight copy/paste of some allegedly working examples in lib-gwt-svg-sampels.  Can you see what I'm doing wrong?  Is it possible that this is a casualty of the gwt 2.7 migration?  

Any help would be appreciated...


- Geoff

Lukas Laag

unread,
Mar 24, 2015, 6:09:58 PM3/24/15
to lib-g...@googlegroups.com
When you use styleName='{style.myStyle}', what happens behind the
curtain is that some UiBinder-generated java code calls
http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/UIObject.html#setStyleName%28java.lang.String,%20boolean%29,
which in turns sets the Element classname javascript property. This does
not work for the SVG DOM, because, though SVG DOM objects also have a
classname property, it is not a string, but an SVGAnimatedString
(because CSS classname can be animated in SVG). Thus, in javascript, one
needs to change the classname.baseVal property to set the CSS className.
This is what is done the
http://www.vectomatic.org/mvn-sites/lib-gwt-svg/apidocs/org/vectomatic/dom/svg/OMSVGElement.html#setClassNameBaseVal%28java.lang.String%29,
a method which is callable by UiBinder-generated code.

What you suggest:
<ui:style>
.searchButton { float: left; padding-left: 10px; width: 25px; height:
25px; }
</ui:style>
...
<svg:SVGImage ui:field='searchButton' resource='{res.glass}'
classNameBaseVal='{style.searchButton}' />

ought to work as it is the same thing I do in my widget sample
http://www.vectomatic.org/gwt/lib-gwt-svg-samples-latest/lib-gwt-svg-samples.html.
Since the sample is based on 2.7.0 and works, I do not think the problem
is related to a migration problem to 2.7.0

The error message you indicate seems to indicate that the resource is
somehow not set (the SVGImage svgElement, which ought to be se by
resource='{res.glass}', is undefined). Do you have a line like:
<ui:with field='res' type='...' />. Does it contain SVGResource or
SVGExternalResource ? In the latter case it probably would not work as
the svgElement would not be immediately available, but later, after the
async call to load the resource has completed.

Could this be a browser or OS problem ? I develop/test on linux
(opensuse13.2)+firefox(36) or chromium(41). Does the widget sample work
on your system ?
Otherwise there has to be a subtle difference someplace accounting for
the different behavior. I do not know how I can help you unless you can
create a minimalistic sample I could debug. Maybe another idea would be
to look at the generated code (in target/gen)

Lukas



Geoff Huenemann

unread,
Mar 25, 2015, 12:54:39 AM3/25/15
to lib-g...@googlegroups.com
Yes, there is a definition of:

    <ui:with field='res' type='com.jostleme.jostle.ui.rich.client.JostleClientBundle'/>

and JostleClientBundle includes:

@Source("com/jostleme/jostle/ui/rich/client/imgBundle/glass.svg")
public SVGResource glass();

I agree that it looks like the element isn't there yet, and I suspected the external resource problem you mention, but that doesn't seem to be the issue.  And as I say, if I just remove the classNameBaseVal bit, it works fine. 

So you're saying your samples definitely work with GWT 2.7 for you?  In that case, I agree that there has to be something subtly wrong with my setup, because I copied a couple of them into my file and couldn't get them to work either.  Hmmmmmm.

I'll try again tomorrow.  Thanks for your help.

Geoff Huenemann

unread,
Mar 25, 2015, 12:31:23 PM3/25/15
to lib-g...@googlegroups.com
So looking at your examples (http://www.vectomatic.org/gwt/lib-gwt-svg-samples-latest/lib-gwt-svg-samples.html) again, your UiBinder code is mostly not setting the className.for the SVG, just the class (styleName) for the svgContainer.  I can do that too with no trouble, but it's an extra div (no big deal) and isn't quite the same thing (setting fill colour wouldn't work, for instance).

It is setting the style on the "widgets" page, in the "hearts" svg, for instance.  However, when I copy that exact style and SVGImage declaration into my UiBinder code, it fails with the error mentioned above:

com.google.gwt.core.client.JavaScriptException: (TypeError) : Cannot read property 'setClassNameBaseVal_2_g$' of undefined
Unknown.setClassNameBaseVal_1_g$(richclient-0.js@23:375574)
Unknown.build_hearts_0_g$(richclient-0.js@15:163254)
Unknown.get_hearts_0_g$(richclient-0.js@15:163422)

The SVG I'm using is an SVGResource (not external) and works in all other expected ways.  PNGs in the same resource bundle (ImageResources) have no trouble setting styleName in analogous usages.

I'm not sure how much more time I can spend on this problem, given that I have a workaround, but I'd love to understand the pathology here.  Your library has otherwise been very useful to us, and we will continue to use it (at least until native SVG support comes to GWT...)

Any insight would be appreciated.

Thanks,
Geoff
Reply all
Reply to author
Forward
0 new messages