Browse Source

Update theme resource references for legacy components (#17027)

Change-Id: Id4f119b22d44f6abf63e730442e22a34e7c1953f
tags/7.6.0.alpha2
Artur Signell 9 years ago
parent
commit
86fb07068f

+ 8
- 7
client/src/com/vaadin/client/ui/VFilterSelect.java View File

@@ -79,6 +79,7 @@ import com.vaadin.shared.AbstractComponentState;
import com.vaadin.shared.EventId;
import com.vaadin.shared.ui.ComponentStateUtil;
import com.vaadin.shared.ui.combobox.FilteringMode;
import com.vaadin.shared.util.SharedUtil;

/**
* Client side implementation of the Select component.
@@ -98,7 +99,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,

private final String key;
private final String caption;
private String iconUri;
private String untranslatedIconUri;

/**
* Constructor
@@ -110,8 +111,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
key = uidl.getStringAttribute("key");
caption = uidl.getStringAttribute("caption");
if (uidl.hasAttribute("icon")) {
iconUri = client.translateVaadinUri(uidl
.getStringAttribute("icon"));
untranslatedIconUri = uidl.getStringAttribute("icon");
}
}

@@ -124,7 +124,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public String getDisplayString() {
final StringBuffer sb = new StringBuffer();
final Icon icon = client.getIcon(iconUri);
final Icon icon = client.getIcon(client
.translateVaadinUri(untranslatedIconUri));
if (icon != null) {
sb.append(icon.getElement().getString());
}
@@ -164,7 +165,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @return
*/
public String getIconUri() {
return iconUri;
return client.translateVaadinUri(untranslatedIconUri);
}

/**
@@ -190,8 +191,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
|| (caption != null && !caption.equals(other.caption))) {
return false;
}
if ((iconUri == null && other.iconUri != null)
|| (iconUri != null && !iconUri.equals(other.iconUri))) {
if (!SharedUtil.equals(untranslatedIconUri,
other.untranslatedIconUri)) {
return false;
}
return true;

+ 2
- 3
client/src/com/vaadin/client/ui/VScrollTable.java View File

@@ -1647,8 +1647,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
actionMap.put(key + "_c", caption);
if (action.hasAttribute("icon")) {
// TODO need some uri handling ??
actionMap.put(key + "_i", client.translateVaadinUri(action
.getStringAttribute("icon")));
actionMap.put(key + "_i", action.getStringAttribute("icon"));
} else {
actionMap.remove(key + "_i");
}
@@ -1661,7 +1660,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}

public String getActionIcon(String actionKey) {
return actionMap.get(actionKey + "_i");
return client.translateVaadinUri(actionMap.get(actionKey + "_i"));
}

private void updateHeader(String[] strings) {

+ 51
- 0
client/src/com/vaadin/client/ui/ui/UIConnector.java View File

@@ -1005,6 +1005,8 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
activeTheme);
}

String oldThemeBase = getConnection().translateVaadinUri("theme://");

activeTheme = newTheme;

if (newTheme != null) {
@@ -1013,12 +1015,61 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
activeTheme);

updateVaadinFavicon(newTheme);

}

forceStateChangeRecursively(UIConnector.this);
// UIDL has no stored URL which we can repaint so we do some find and
// replace magic...
String newThemeBase = getConnection().translateVaadinUri("theme://");
replaceThemeAttribute(oldThemeBase, newThemeBase);

getLayoutManager().forceLayout();
}

/**
* Finds all attributes where theme:// urls have possibly been used and
* replaces any old theme url with a new one
*
* @param oldPrefix
* The start of the old theme URL
* @param newPrefix
* The start of the new theme URL
*/
private void replaceThemeAttribute(String oldPrefix, String newPrefix) {
// Images
replaceThemeAttribute("src", oldPrefix, newPrefix);
// Embedded flash
replaceThemeAttribute("value", oldPrefix, newPrefix);
replaceThemeAttribute("movie", oldPrefix, newPrefix);
}

/**
* Finds any attribute of the given type where theme:// urls have possibly
* been used and replaces any old theme url with a new one
*
* @param attributeName
* The name of the attribute, e.g. "src"
* @param oldPrefix
* The start of the old theme URL
* @param newPrefix
* The start of the new theme URL
*/
private void replaceThemeAttribute(String attributeName, String oldPrefix,
String newPrefix) {
// Find all "attributeName=" which start with "oldPrefix" using e.g.
// [^src='http://oldpath']
NodeList<Element> elements = querySelectorAll("[" + attributeName
+ "^='" + oldPrefix + "']");
for (int i = 0; i < elements.getLength(); i++) {
Element element = elements.getItem(i);
element.setAttribute(
attributeName,
element.getAttribute(attributeName).replace(oldPrefix,
newPrefix));
}
}

/**
* Force a full recursive recheck of every connector's state variables.
*

+ 101
- 0
uitest/src/com/vaadin/tests/themes/LegacyComponentThemeChange.java View File

@@ -0,0 +1,101 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
*
* 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.vaadin.tests.themes;

import com.vaadin.annotations.Theme;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUIWithLog;
import com.vaadin.tests.util.PersonContainer;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;

@Theme("reindeer")
public class LegacyComponentThemeChange extends AbstractTestUIWithLog {

@Override
protected void setup(VaadinRequest request) {
VerticalLayout vl = new VerticalLayout();
vl.setCaption("Change theme by clicking a button");
HorizontalLayout hl = new HorizontalLayout();
for (final String theme : new String[] { "reindeer", "runo" }) {
Button b = new Button(theme);
b.setId(theme + "");
b.addClickListener(new ClickListener() {

@Override
public void buttonClick(ClickEvent event) {
getUI().setTheme(theme);
}
});
hl.addComponent(b);
}
vl.addComponent(hl);

// Always wants to use icon from Runo, even if we change theme
ThemeResource alwaysTheSameIconImage = new ThemeResource(
"../runo/icons/16/ok.png");
ThemeResource varyingIcon = new ThemeResource("menubar-theme-icon.png");
MenuBar bar = new MenuBar();
bar.addItem("runo", alwaysTheSameIconImage, null);
bar.addItem("seletedtheme", varyingIcon, null);

vl.addComponent(bar);

ComboBox cb = new ComboBox("ComboBox");
cb.addItem("No icon");
cb.addItem("Icon");
cb.setItemIcon("Icon", new ThemeResource("comboboxicon.png"));
cb.setValue("Icon");

vl.addComponent(cb);

Embedded e = new Embedded("embedded");
e.setMimeType("application/x-shockwave-flash");
e.setType(Embedded.TYPE_OBJECT);
e.setSource(new ThemeResource("embedded.src"));
vl.addComponent(e);

Table t = new Table();
t.addActionHandler(new Handler() {
@Override
public void handleAction(Action action, Object sender, Object target) {
}

@Override
public Action[] getActions(Object target, Object sender) {
return new Action[] { new Action("Theme icon",
new ThemeResource("action-icon.png")) };
}
});
PersonContainer pc = PersonContainer.createWithTestData();
pc.addNestedContainerBean("address");
t.setContainerDataSource(pc);
vl.addComponent(t);

addComponent(vl);
}

}

+ 163
- 0
uitest/src/com/vaadin/tests/themes/LegacyComponentThemeChangeTest.java View File

@@ -0,0 +1,163 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
*
* 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.vaadin.tests.themes;

import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedCondition;

import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.ComboBoxElement;
import com.vaadin.testbench.elements.EmbeddedElement;
import com.vaadin.testbench.elements.MenuBarElement;
import com.vaadin.testbench.elements.TableElement;
import com.vaadin.testbench.parallel.Browser;
import com.vaadin.testbench.parallel.BrowserUtil;
import com.vaadin.tests.tb3.MultiBrowserTest;

public class LegacyComponentThemeChangeTest extends MultiBrowserTest {

@Override
public List<DesiredCapabilities> getBrowsersToTest() {
// Seems like stylesheet onload is not fired on PhantomJS
// https://github.com/ariya/phantomjs/issues/12332
List<DesiredCapabilities> l = getBrowsersExcludingPhantomJS();

// For some reason, IE times out when trying to open the combobox,
// #18341
l.remove(Browser.IE11.getDesiredCapabilities());
return l;
}

@Test
public void legacyComponentThemeResourceChange() {
openTestURL();
String theme = "reindeer";
assertMenubarTheme(theme);
assertCombobBoxTheme(theme);
assertTableTheme(theme);
assertEmbeddedTheme(theme);

theme = "runo";
changeTheme(theme);
assertMenubarTheme(theme);
assertCombobBoxTheme(theme);
assertTableTheme(theme);
assertEmbeddedTheme(theme);

theme = "reindeer";
changeTheme(theme);
assertMenubarTheme(theme);
assertCombobBoxTheme(theme);
assertTableTheme(theme);
assertEmbeddedTheme(theme);

}

private void assertEmbeddedTheme(String theme) {
if (BrowserUtil.isIE8(getDesiredCapabilities())) {
// IE8 won't initialize the dummy flash properly
return;
}
EmbeddedElement e = $(EmbeddedElement.class).first();
WebElement movieParam = e.findElement(By
.xpath(".//param[@name='movie']"));
WebElement embed = e.findElement(By.xpath(".//embed"));
assertAttributePrefix(movieParam, "value", theme);
assertAttributePrefix(embed, "src", theme);
assertAttributePrefix(embed, "movie", theme);
}

private void assertTableTheme(String theme) {
TableElement t = $(TableElement.class).first();
t.getRow(0).contextClick();
WebElement popup = findElement(By.className("v-contextmenu"));

WebElement actionImage = popup.findElement(By.xpath(".//img"));
assertAttributePrefix(actionImage, "src", theme);
}

private void assertCombobBoxTheme(String theme) {
ComboBoxElement cb = $(ComboBoxElement.class).first();
WebElement selectedImage = cb.findElement(By.xpath("./img"));
assertAttributePrefix(selectedImage, "src", theme);

cb.openPopup();
WebElement popup = findElement(By
.className("v-filterselect-suggestpopup"));
WebElement itemImage = popup.findElement(By.xpath(".//img"));
assertAttributePrefix(itemImage, "src", theme);
}

private void assertMenubarTheme(String theme) {
// The runoImage must always come from Runo
WebElement runoImage = $(MenuBarElement.class).first().findElement(
By.xpath(".//span[text()='runo']/img"));
String runoImageSrc = runoImage.getAttribute("src");

// Something in Selenium normalizes the image so it becomes
// "/themes/runo/icons/16/ok.png" here although it is
// "/themes/<currenttheme>/../runo/icons/16/ok.png" in the browser
Assert.assertEquals(getThemeURL("runo") + "icons/16/ok.png",
runoImageSrc);

// The other image should change with the theme
WebElement themeImage = $(MenuBarElement.class).first().findElement(
By.xpath(".//span[text()='seletedtheme']/img"));
assertAttributePrefix(themeImage, "src", theme);
}

private void assertAttributePrefix(WebElement element, String attribute,
String theme) {
String value = element.getAttribute(attribute);
String expectedPrefix = getThemeURL(theme);
Assert.assertTrue("Attribute " + attribute + "='" + value
+ "' does not start with " + expectedPrefix,
value.startsWith(expectedPrefix));

}

private String getThemeURL(String theme) {
return getBaseURL() + "/VAADIN/themes/" + theme + "/";
}

private void changeTheme(String theme) {
$(ButtonElement.class).id(theme).click();
waitForThemeToChange(theme);
}

private void waitForThemeToChange(final String theme) {

final WebElement rootDiv = findElement(By
.xpath("//div[contains(@class,'v-app')]"));
waitUntil(new ExpectedCondition<Boolean>() {

@Override
public Boolean apply(WebDriver input) {
String rootClass = rootDiv.getAttribute("class").trim();

return rootClass.contains(theme);
}
}, 30);
}

}

Loading…
Cancel
Save