Change-Id: I835756b240bc9ece885acdc8f43ec6a1599bb7c5tags/7.4.0.beta1
@@ -685,7 +685,7 @@ public class AbsoluteLayout extends AbstractLayout implements | |||
// handle children | |||
for (Element childComponent : design.children()) { | |||
Attributes attr = childComponent.attributes(); | |||
Component newChild = designContext.createChild(childComponent); | |||
Component newChild = designContext.readDesign(childComponent); | |||
StringBuilder css = new StringBuilder(); | |||
if (attr.hasKey(ATTR_TOP)) { | |||
css.append("top:").append(attr.get(ATTR_TOP)).append(";"); |
@@ -930,7 +930,7 @@ public abstract class AbstractComponent extends AbstractClientConnector | |||
} | |||
// handle immediate | |||
if (attr.hasKey("immediate")) { | |||
setImmediate(DesignAttributeHandler.getBoolean(attr | |||
setImmediate(DesignAttributeHandler.parseBoolean(attr | |||
.get("immediate"))); | |||
} | |||
@@ -955,7 +955,7 @@ public abstract class AbstractComponent extends AbstractClientConnector | |||
// handle responsive | |||
if (attr.hasKey("responsive")) { | |||
setResponsive(DesignAttributeHandler.getBoolean(attr | |||
setResponsive(DesignAttributeHandler.parseBoolean(attr | |||
.get("responsive"))); | |||
} | |||
// check for unsupported attributes |
@@ -485,7 +485,7 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements | |||
// handle children | |||
for (Element childComponent : design.children()) { | |||
Attributes attr = childComponent.attributes(); | |||
Component newChild = designContext.createChild(childComponent); | |||
Component newChild = designContext.readDesign(childComponent); | |||
addComponent(newChild); | |||
// handle alignment | |||
int bitMask = 0; |
@@ -297,7 +297,7 @@ public abstract class AbstractSingleComponentContainer extends | |||
+ " can have only one child component."); | |||
} else if (childCount == 1) { | |||
Element childElement = design.children().get(0); | |||
Component newChild = designContext.createChild(childElement); | |||
Component newChild = designContext.readDesign(childElement); | |||
setContent(newChild); | |||
} | |||
} |
@@ -610,7 +610,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { | |||
"A split panel can contain at most two components."); | |||
} | |||
for (Element childElement : design.children()) { | |||
Component childComponent = designContext.createChild(childElement); | |||
Component childComponent = designContext.readDesign(childElement); | |||
if (childElement.hasAttr(":second")) { | |||
setSecondComponent(childComponent); | |||
} else { |
@@ -369,7 +369,7 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { | |||
super.readDesign(design, designContext); | |||
// handle children | |||
for (Element childComponent : design.children()) { | |||
Component newChild = designContext.createChild(childComponent); | |||
Component newChild = designContext.readDesign(childComponent); | |||
addComponent(newChild); | |||
} | |||
} |
@@ -1492,7 +1492,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, | |||
} | |||
// create the component that is in tab content | |||
Element content = tabElement.child(0); | |||
Component child = designContext.createChild(content); | |||
Component child = designContext.readDesign(content); | |||
Tab tab = this.addTab(child); | |||
if (attr.hasKey("visible")) { | |||
tab.setVisible(DesignAttributeHandler.readAttribute("visible", |
@@ -177,9 +177,9 @@ public class Design implements Serializable { | |||
* id/local id/caption | |||
*/ | |||
private static DesignContext designToComponentTree(Document doc, | |||
Component componentRoot, Class<? extends Component> classWithFields) { | |||
Component componentRoot, Class<?> classWithFields) { | |||
DesignContext designContext = new DesignContext(doc); | |||
designContext.getPrefixes(doc); | |||
designContext.readPackageMappings(doc); | |||
// No special handling for a document without a body element - should be | |||
// taken care of by jsoup. | |||
Element root = doc.body(); | |||
@@ -210,7 +210,7 @@ public class Design implements Serializable { | |||
}; | |||
designContext.addComponentCreationListener(creationListener); | |||
// create subtree | |||
designContext.synchronizeAndRegister(componentRoot, element); | |||
designContext.readDesign(element, componentRoot); | |||
// make sure that all the member fields are bound | |||
Collection<String> unboundFields = binder.getUnboundFields(); | |||
if (!unboundFields.isEmpty()) { | |||
@@ -222,7 +222,7 @@ public class Design implements Serializable { | |||
designContext.removeComponentCreationListener(creationListener); | |||
} else { | |||
// createChild creates the entire component hierarchy | |||
componentRoot = designContext.createChild(element); | |||
componentRoot = designContext.readDesign(element); | |||
} | |||
designContext.setRootComponent(componentRoot); | |||
return designContext; | |||
@@ -257,7 +257,7 @@ public class Design implements Serializable { | |||
Component root = designContext.getRootComponent(); | |||
Node rootNode = designContext.createElement(root); | |||
body.appendChild(rootNode); | |||
designContext.storePrefixes(doc); | |||
designContext.writePackageMappings(doc); | |||
return doc; | |||
} | |||
@@ -61,7 +61,7 @@ import com.vaadin.ui.Component; | |||
*/ | |||
public class DesignAttributeHandler implements Serializable { | |||
protected static Logger getLogger() { | |||
private static Logger getLogger() { | |||
return Logger.getLogger(DesignAttributeHandler.class.getName()); | |||
} | |||
@@ -423,7 +423,7 @@ public class DesignAttributeHandler implements Serializable { | |||
// it is present and the value is not "false" or "FALSE". Thus empty | |||
// value evaluates to true. | |||
if (targetType == Boolean.TYPE || targetType == Boolean.class) { | |||
return !value.equalsIgnoreCase("false"); | |||
return parseBoolean(value); | |||
} | |||
if (targetType == Integer.TYPE || targetType == Integer.class) { | |||
return Integer.valueOf(value); | |||
@@ -716,15 +716,14 @@ public class DesignAttributeHandler implements Serializable { | |||
* Converts the given string attribute value to its corresponding boolean. | |||
* | |||
* An empty string and "true" are considered to represent a true value and | |||
* "false" to represent a false value. All other input will throw an | |||
* exception | |||
* "false" to represent a false value. | |||
* | |||
* @param booleanValue | |||
* the boolean value from an attribute | |||
* @return the parsed boolean | |||
*/ | |||
public static boolean getBoolean(String booleanValue) { | |||
return "".equals(booleanValue) ? true : Boolean.valueOf(booleanValue); | |||
public static boolean parseBoolean(String booleanValue) { | |||
return !booleanValue.equalsIgnoreCase("false"); | |||
} | |||
} |
@@ -29,7 +29,6 @@ import org.jsoup.nodes.Element; | |||
import org.jsoup.nodes.Node; | |||
import com.vaadin.annotations.DesignRoot; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.HasComponents; | |||
@@ -261,19 +260,18 @@ public class DesignContext implements Serializable { | |||
* @return the default instance for the given class. The return value must | |||
* not be modified by the caller | |||
*/ | |||
public <T> T getDefaultInstance(AbstractComponent abstractComponent) { | |||
public <T> T getDefaultInstance(Component component) { | |||
// If the root is a @DesignRoot component, it can't use itself as a | |||
// reference or the written design will be empty | |||
// If the root component in some other way initializes itself in the | |||
// constructor | |||
if (getRootComponent() == abstractComponent | |||
&& abstractComponent.getClass().isAnnotationPresent( | |||
DesignRoot.class)) { | |||
return (T) getDefaultInstance((Class<? extends Component>) abstractComponent | |||
if (getRootComponent() == component | |||
&& component.getClass().isAnnotationPresent(DesignRoot.class)) { | |||
return (T) getDefaultInstance((Class<? extends Component>) component | |||
.getClass().getSuperclass()); | |||
} | |||
return (T) getDefaultInstance(abstractComponent.getClass()); | |||
return (T) getDefaultInstance(component.getClass()); | |||
} | |||
private Component getDefaultInstance( | |||
@@ -295,11 +293,10 @@ public class DesignContext implements Serializable { | |||
} | |||
/** | |||
* Get and store the mappings from prefixes to package names from meta tags | |||
* located under <head> in the html document. | |||
* | |||
* Reads and stores the mappings from prefixes to package names from meta | |||
* tags located under <head> in the html document. | |||
*/ | |||
protected void getPrefixes(Document doc) { | |||
protected void readPackageMappings(Document doc) { | |||
Element head = doc.head(); | |||
if (head == null) { | |||
return; | |||
@@ -329,14 +326,15 @@ public class DesignContext implements Serializable { | |||
} | |||
/** | |||
* Stores the package mappings (prefix -> package name) of this object to | |||
* the specified document. The prefixes are stored as <meta> tags under | |||
* <head> in the document. | |||
* Writes the package mappings (prefix -> package name) of this object to | |||
* the specified document. | |||
* <p> | |||
* The prefixes are stored as <meta> tags under <head> in the document. | |||
* | |||
* @param doc | |||
* the Jsoup document tree where the package mappings are stored | |||
* the Jsoup document tree where the package mappings are written | |||
*/ | |||
public void storePrefixes(Document doc) { | |||
public void writePackageMappings(Document doc) { | |||
Element head = doc.head(); | |||
for (String prefix : prefixToPackage.keySet()) { | |||
// Only store the prefix-name mapping if it is not a default mapping | |||
@@ -348,7 +346,6 @@ public class DesignContext implements Serializable { | |||
+ prefixToPackage.get(prefix); | |||
newNode.attr("content", prefixToPackageName); | |||
head.appendChild(newNode); | |||
} | |||
} | |||
} | |||
@@ -414,38 +411,36 @@ public class DesignContext implements Serializable { | |||
} | |||
/** | |||
* Creates a Component corresponding to the given html node. Also calls | |||
* readDesign() for the created node, in effect creating the entire | |||
* component hierarchy rooted at the returned component. | |||
* Reads the given design node and creates the corresponding component tree | |||
* | |||
* @param componentDesign | |||
* The html tree node containing the description of the component | |||
* to be created. | |||
* @return a Component corresponding to componentDesign | |||
* The design element containing the description of the component | |||
* to be created | |||
* @return the root component of component tree | |||
*/ | |||
public Component createChild(Element componentDesign) { | |||
public Component readDesign(Element componentDesign) { | |||
// Create the component. | |||
Component component = instantiateComponent(componentDesign); | |||
synchronizeAndRegister(component, componentDesign); | |||
readDesign(componentDesign, component); | |||
fireComponentCreatedEvent(componentToLocalId.get(component), component); | |||
return component; | |||
} | |||
/** | |||
* Calls readDesign() for the given component and passes the given component | |||
* design as a parameter. This creates the entire component hierarchy rooted | |||
* at the given component. Also registers the componentid, localId and | |||
* caption of the given component and all its children to the context | |||
* | |||
* @param component | |||
* The component to be synchronized from design | |||
* Reads the given design node and populates the given component with the | |||
* corresponding component tree | |||
* <p> | |||
* Additionally registers the component id, local id and caption of the | |||
* given component and all its children in the context | |||
* | |||
* @param componentDesign | |||
* The html tree node containing the description of the component | |||
* @throws DesignException | |||
* if the design contains duplicate local or global ids | |||
* The design element containing the description of the component | |||
* to be created | |||
* @param component | |||
* The component which corresponds to the design element | |||
*/ | |||
public void synchronizeAndRegister(Component component, | |||
Element componentDesign) { | |||
public void readDesign(Element componentDesign, Component component) { | |||
component.readDesign(componentDesign, this); | |||
// Get the ids and the caption of the component and store them in the | |||
// maps of this design context. |
@@ -114,7 +114,7 @@ public class TestLocale extends TestCase { | |||
html.appendChild(doc.createElement("head")); | |||
Element body = doc.createElement("body"); | |||
html.appendChild(body); | |||
dc.storePrefixes(doc); | |||
dc.writePackageMappings(doc); | |||
// Append the design under <body> in the html tree. createNode | |||
// creates the entire component hierarchy rooted at the |
@@ -78,7 +78,7 @@ public class TestReadDesign extends TestCase { | |||
private AbsoluteLayout createLayout() { | |||
DesignContext ctx = new DesignContext(); | |||
Element design = createDesign(); | |||
Component child = ctx.createChild(design); | |||
Component child = ctx.readDesign(design); | |||
return (AbsoluteLayout) child; | |||
} | |||
@@ -110,6 +110,7 @@ public class TestReadDesign extends TestCase { | |||
// Synchronize with a design having no immediate attribute - | |||
// explicitImmediate should then be null. | |||
design = createDesign("description", "test-description"); | |||
component = getComponent(); | |||
component.readDesign(design, ctx); | |||
// Synchronize with a design having immediate = false | |||
design = createDesign("immediate", "false"); |
@@ -80,7 +80,7 @@ public class TestReadDesign extends TestCase { | |||
String... alignments) { | |||
DesignContext ctx = new DesignContext(); | |||
Element design = createDesign(expandRatio, margin, alignments); | |||
Component child = ctx.createChild(design); | |||
Component child = ctx.readDesign(design); | |||
return (VerticalLayout) child; | |||
} | |||
@@ -76,7 +76,7 @@ public class TestReadDesign extends TestCase { | |||
attributes.put("icon-alt", "OK"); | |||
attributes.put("click-shortcut", "ctrl-shift-o"); | |||
Button button = (Button) ctx | |||
.createChild(createButtonWithAttributes(attributes)); | |||
.readDesign(createButtonWithAttributes(attributes)); | |||
assertEquals(3, button.getTabIndex()); | |||
assertEquals(false, button.isHtmlContentAllowed()); | |||
assertEquals("OK", button.getIconAlternateText()); | |||
@@ -94,9 +94,9 @@ public class TestReadDesign extends TestCase { | |||
*/ | |||
private void createAndTestButtons(String content, String caption) { | |||
Element e1 = createElement("v-button", content, caption); | |||
Button b1 = (Button) ctx.createChild(e1); | |||
Button b1 = (Button) ctx.readDesign(e1); | |||
Element e2 = createElement("v-native-button", content, caption); | |||
NativeButton b2 = (NativeButton) ctx.createChild(e2); | |||
NativeButton b2 = (NativeButton) ctx.readDesign(e2); | |||
if (content != null) { | |||
assertEquals("The button has the wrong text content.", content, | |||
b1.getCaption()); |
@@ -43,7 +43,7 @@ public class TestReadDesign extends TestCase { | |||
@Test | |||
public void testChecked() { | |||
Element e = createElement(true); | |||
CheckBox box = (CheckBox) ctx.createChild(e); | |||
CheckBox box = (CheckBox) ctx.readDesign(e); | |||
assertEquals("The checkbox must be checked", Boolean.TRUE, | |||
box.getValue()); | |||
} | |||
@@ -51,7 +51,7 @@ public class TestReadDesign extends TestCase { | |||
@Test | |||
public void testUnchecked() { | |||
Element e = createElement(false); | |||
CheckBox box = (CheckBox) ctx.createChild(e); | |||
CheckBox box = (CheckBox) ctx.readDesign(e); | |||
assertEquals("The checkbox must be unchecked", Boolean.FALSE, | |||
box.getValue()); | |||
} |
@@ -47,7 +47,7 @@ public class TestReadDesign extends TestCase { | |||
private CssLayout createLayout() { | |||
DesignContext ctx = new DesignContext(); | |||
Element design = createDesign(); | |||
Component child = ctx.createChild(design); | |||
Component child = ctx.readDesign(design); | |||
return (CssLayout) child; | |||
} | |||
@@ -70,7 +70,7 @@ public class TestReadDesign extends TestCase { | |||
*/ | |||
private void createAndTestLabel(String content, String caption) { | |||
Element e = createElement("v-label", content, caption); | |||
Label l = (Label) ctx.createChild(e); | |||
Label l = (Label) ctx.readDesign(e); | |||
if (content != null) { | |||
assertEquals("The label has wrong text content.", content, | |||
l.getValue()); |