blob: de8fc3092ca4761f6311db8d2abfc907311abff9 [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.uibinder.test.client;
import com.google.gwt.dom.builder.client.DomBuilderFactory;
import com.google.gwt.dom.builder.shared.DivBuilder;
import com.google.gwt.dom.builder.shared.ElementBuilderBase;
import com.google.gwt.dom.builder.shared.ElementBuilderFactory;
import com.google.gwt.dom.builder.shared.HtmlBuilderFactory;
import com.google.gwt.dom.builder.shared.HtmlElementBuilderBase;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.IsRenderable;
import com.google.gwt.user.client.ui.PotentialElement;
import com.google.gwt.user.client.ui.RenderableStamper;
import com.google.gwt.user.client.ui.Widget;
/**
* Used by {@link IsRenderableIntegrationTest}. A simple implementation of
* IsRenderable. Note that the actual building for both string based and dom
* based versions happens in one place, {@link #build(ElementBuilderFactory)}.
* <p>
* Note also that that the widget's contents are simply re-rendered when the
* widget's state changes, in this case in {@link #setText}. This is a bad idea
* for large widgets, but for little leaf widgets like this one is probably just
* fine.
* <p>
* It would probably be a good refactor a production super class out of this
* once the IsRenderable interface settles down.
* <p>
* It's HasValue aspect is just meant for unit testing, not anything to
* generalize.
*/
public class SimpleRenderable extends Widget implements IsRenderable, HasText, HasValue<Object> {
private String text = "";
private Object value;
public SimpleRenderable() {
setElement(PotentialElement.build(this));
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Object> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
@Override
public void claimElement(Element element) {
setElement(element);
}
public String getText() {
return text;
}
@Override
public Object getValue() {
return value;
}
@Override
public void initializeClaimedElement() {
}
@Override
public SafeHtml render(RenderableStamper stamper) {
HtmlBuilderFactory factory = HtmlBuilderFactory.get();
String realText = text;
text = "[string built]" + text;
HtmlElementBuilderBase<?> builder = (HtmlElementBuilderBase<?>) build(factory);
text = realText;
return stamper.stamp(builder.asSafeHtml());
}
@Override
public void render(RenderableStamper stamper, SafeHtmlBuilder safeHtmlBuilder) {
safeHtmlBuilder.append(render(stamper));
}
@Override
public Element resolvePotentialElement() {
String realText = text;
text = "[dom built]" + text;
ElementBuilderBase<?> builder = build(DomBuilderFactory.get());
text = realText;
setElement(builder.finish());
return getElement();
}
@Override
public void setText(String text) {
this.text = text;
updateElement();
}
@Override
public void setValue(Object value) {
setValue(value, false);
}
@Override
public void setValue(Object newValue, boolean fireEvents) {
Object oldValue = value;
value = newValue;
ValueChangeEvent.fireIfNotEqual(this, oldValue, newValue);
}
private ElementBuilderBase<?> build(ElementBuilderFactory factory) {
DivBuilder builder = factory.createDivBuilder();
builder.text(text).end();
return builder;
}
private boolean domIsReal() {
return !PotentialElement.isPotential(getElement());
}
private void updateElement() {
if (domIsReal()) {
String realText = text;
text = "[updated]" + text;
/*
* Sleazey. If this is to get real, should split rendering into the outer
* builder and the inner builder. Update can just call the inner builder.
* But we'd still have to make a bunch of dom calls to tear down the old
* guts, something like while (el.firstChild) {
* el.removeChild(el.firstChild); }
*
* Have to wonder if that actually would be any faster than rebuilding the
* guts as string
*/
ElementBuilderBase<?> builder = build(DomBuilderFactory.get());
getElement().setInnerHTML(builder.finish().getInnerHTML());
text = realText;
}
}
}