You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2012/07/16 19:51:01 UTC
git commit: WICKET-4593 bi-directional model second try,
more tests for TabbedPanel
Updated Branches:
refs/heads/master 55cd66005 -> 0f9349b62
WICKET-4593 bi-directional model second try, more tests for TabbedPanel
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/0f9349b6
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/0f9349b6
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/0f9349b6
Branch: refs/heads/master
Commit: 0f9349b629017299b37f5f4841569f16dce732bc
Parents: 55cd660
Author: svenmeier <sv...@apache.org>
Authored: Mon Jul 16 19:50:37 2012 +0200
Committer: svenmeier <sv...@apache.org>
Committed: Mon Jul 16 19:50:37 2012 +0200
----------------------------------------------------------------------
.../extensions/markup/html/tabs/TabbedPanel.java | 108 ++++++--
.../markup/html/tabs/TabbedPanelTest.java | 193 ++++++++++++++-
2 files changed, 265 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/0f9349b6/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.java
index 8fa9d50..c8b2b47 100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.java
@@ -34,7 +34,7 @@ import org.apache.wicket.util.lang.Args;
/**
- * TabbedPanel component represets a panel with tabs that are used to switch between different
+ * TabbedPanel component represents a panel with tabs that are used to switch between different
* content panels inside the TabbedPanel panel.
* <p>
* <b>Note:</b> When the currently selected tab is replaced by changing the underlying list of tabs,
@@ -81,6 +81,9 @@ public class TabbedPanel<T extends ITab> extends Panel
private final List<T> tabs;
+ /** the current tab */
+ private int currentTab = -1;
+
private transient Boolean[] tabsVisibilityCache;
/**
@@ -93,7 +96,22 @@ public class TabbedPanel<T extends ITab> extends Panel
*/
public TabbedPanel(final String id, final List<T> tabs)
{
- super(id, new Model<Integer>(-1));
+ this(id, tabs, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param id
+ * component id
+ * @param tabs
+ * list of ITab objects used to represent tabs
+ * @param model
+ * model holding the index of the selected tab
+ */
+ public TabbedPanel(final String id, final List<T> tabs, IModel<Integer> model)
+ {
+ super(id, model);
this.tabs = Args.notNull(tabs, "tabs");
@@ -134,6 +152,25 @@ public class TabbedPanel<T extends ITab> extends Panel
return newTabContainer(iteration);
}
});
+
+ add(newPanel());
+ }
+
+ /**
+ * Initialize the component's model.
+ *
+ * @return a new model containing {@code -1} if the super implementation doesn't supply one
+ */
+ @Override
+ protected IModel<?> initModel()
+ {
+ IModel<?> model = super.initModel();
+ if (model == null)
+ {
+ model = new Model<Integer>(-1);
+ }
+
+ return model;
}
/**
@@ -207,38 +244,32 @@ public class TabbedPanel<T extends ITab> extends Panel
@Override
protected void onBeforeRender()
{
- if (tabs.size() == 0)
- {
- // force an empty container to be created every time if we have no tabs
- setSelectedTab(0);
- }
- else if ((getSelectedTab() == -1) || (isTabVisible(getSelectedTab()) == false))
+ int index = getSelectedTab();
+
+ if ((index == -1) || (isTabVisible(index) == false))
{
- // find first visible selected tab
- int selected = 0;
+ // find first visible tab
+ index = -1;
for (int i = 0; i < tabs.size(); i++)
{
if (isTabVisible(i))
{
- selected = i;
+ index = i;
break;
}
}
- if (selected == tabs.size())
+ if (index != -1)
{
/*
- * none of the tabs are selected...
- *
- * we do not need to do anything special because the check in setSelectedTab() will
- * replace the current tab panel with an empty one
+ * found a visible tab, so select it
*/
- selected = 0;
+ setSelectedTab(index);
}
-
- setSelectedTab(selected);
}
+ setCurrentTab(index);
+
super.onBeforeRender();
}
@@ -330,32 +361,50 @@ public class TabbedPanel<T extends ITab> extends Panel
* @param index
* index of the tab to select
* @return this for chaining
+ * @throws IndexOutOfBoundsException
+ * if index is not {@code -1} or in the range of available tabs
*/
- public TabbedPanel setSelectedTab(final int index)
+ public TabbedPanel<T> setSelectedTab(final int index)
{
- if ((index < 0) || ((index >= tabs.size()) && (index > 0)))
+ if ((index < 0) || (index >= tabs.size()))
{
throw new IndexOutOfBoundsException();
}
setDefaultModelObject(index);
+ // force the tab's component to be aquired again if already the current tab
+ currentTab = -1;
+ setCurrentTab(index);
+
+ return this;
+ }
+
+ private void setCurrentTab(int index)
+ {
+ if (this.currentTab == index)
+ {
+ // already current
+ return;
+ }
+ this.currentTab = index;
+
final Component component;
- if ((tabs.size() == 0) || !isTabVisible(index))
+ if (currentTab == -1 || (tabs.size() == 0) || !isTabVisible(currentTab))
{
- // no tabs or the currently selected tab is not visible
- component = new WebMarkupContainer(TAB_PANEL_ID);
+ // no tabs or the current tab is not visible
+ component = newPanel();
}
else
{
// show panel from selected tab
- T tab = tabs.get(index);
+ T tab = tabs.get(currentTab);
component = tab.getPanel(TAB_PANEL_ID);
if (component == null)
{
throw new WicketRuntimeException("ITab.getPanel() returned null. TabbedPanel [" +
- getPath() + "] ITab index [" + index + "]");
+ getPath() + "] ITab index [" + currentTab + "]");
}
}
@@ -365,12 +414,15 @@ public class TabbedPanel<T extends ITab> extends Panel
"ITab.getPanel() returned a panel with invalid id [" +
component.getId() +
"]. You must always return a panel with id equal to the provided panelId parameter. TabbedPanel [" +
- getPath() + "] ITab index [" + index + "]");
+ getPath() + "] ITab index [" + currentTab + "]");
}
addOrReplace(component);
+ }
- return this;
+ private WebMarkupContainer newPanel()
+ {
+ return new WebMarkupContainer(TAB_PANEL_ID);
}
/**
http://git-wip-us.apache.org/repos/asf/wicket/blob/0f9349b6/wicket-extensions/src/test/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanelTest.java
----------------------------------------------------------------------
diff --git a/wicket-extensions/src/test/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanelTest.java b/wicket-extensions/src/test/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanelTest.java
index a220375..ab660bf 100644
--- a/wicket-extensions/src/test/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanelTest.java
+++ b/wicket-extensions/src/test/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanelTest.java
@@ -32,15 +32,22 @@ import org.junit.Test;
*/
public class TabbedPanelTest extends WicketTestCase
{
+ /**
+ */
public class TestPage extends WebPage
{
- public TabbedPanel<ITab> tabbedPanel;
+ private static final long serialVersionUID = 1L;
+ protected TabbedPanel<ITab> tabbedPanel;
+
+ /**
+ */
public TestPage()
{
List<ITab> defaultTabs = new ArrayList<ITab>();
defaultTabs.add(new AbstractTab(Model.of("default 1"))
{
+ private static final long serialVersionUID = 1L;
@Override
public WebMarkupContainer getPanel(String panelId)
@@ -50,6 +57,7 @@ public class TabbedPanelTest extends WicketTestCase
});
defaultTabs.add(new AbstractTab(Model.of("default 2"))
{
+ private static final long serialVersionUID = 1L;
@Override
public WebMarkupContainer getPanel(String panelId)
@@ -68,8 +76,16 @@ public class TabbedPanelTest extends WicketTestCase
return new TabbedPanel<ITab>("tabpanel", defaultTabs);
}
+ /**
+ */
public static class TestPanel extends Panel
{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param id
+ * @param panelTestId
+ */
public TestPanel(String id, String panelTestId)
{
super(id);
@@ -77,6 +93,11 @@ public class TabbedPanelTest extends WicketTestCase
}
}
+ /**
+ * No tabs thus no tab component rendered.
+ *
+ * @throws Exception
+ */
@Test
public void renderNoTabs() throws Exception
{
@@ -84,15 +105,20 @@ public class TabbedPanelTest extends WicketTestCase
page.tabbedPanel.getTabs().clear();
tester.startPage(page);
- tester.assertContainsNot("<span wicket:id=\"title\">default 1</span></a>");
+ tester.assertContainsNot("<span wicket:id=\"title\">default 1</span>");
tester.assertContainsNot("<span wicket:id=\"label\">default 1</span>");
- tester.assertContainsNot("<span wicket:id=\"title\">default 2</span></a>");
+ tester.assertContainsNot("<span wicket:id=\"title\">default 2</span>");
tester.assertContainsNot("<span wicket:id=\"label\">default 2</span>");
tester.assertContains("<!-- no panel -->");
- assertEquals(Integer.valueOf(0), page.tabbedPanel.getDefaultModelObject());
+ assertEquals(Integer.valueOf(-1), page.tabbedPanel.getDefaultModelObject());
}
+ /**
+ * Switching between tabsS.
+ *
+ * @throws Exception
+ */
@Test
public void renderDefaultTabsOnly() throws Exception
{
@@ -109,12 +135,19 @@ public class TabbedPanelTest extends WicketTestCase
assertEquals(Integer.valueOf(1), page.tabbedPanel.getDefaultModelObject());
}
+ /**
+ * Additional tabs are rendered.
+ *
+ * @throws Exception
+ */
@Test
public void renderAdditionalTabs() throws Exception
{
TestPage page = tester.startPage(new TestPage());
page.tabbedPanel.getTabs().add(new AbstractTab(Model.of("added 1"))
{
+ private static final long serialVersionUID = 1L;
+
@Override
public WebMarkupContainer getPanel(String panelId)
{
@@ -122,23 +155,167 @@ public class TabbedPanelTest extends WicketTestCase
}
});
// the additional tab isn't rendered yet
- tester.assertContainsNot("<span wicket:id=\"title\">added 1</span></a>");
+ tester.assertContainsNot("<span wicket:id=\"title\">added 1</span>");
tester.assertContainsNot("<span wicket:id=\"label\">added 1</span>");
assertEquals(Integer.valueOf(0), page.tabbedPanel.getDefaultModelObject());
// now its title is visible, but the contents not
tester.clickLink("tabpanel:tabs-container:tabs:1:link");
- tester.assertContains("<span wicket:id=\"title\">added 1</span></a>");
+ tester.assertContains("<span wicket:id=\"title\">added 1</span>");
tester.assertContainsNot("<span wicket:id=\"label\">added 1</span>");
assertEquals(Integer.valueOf(1), page.tabbedPanel.getDefaultModelObject());
// now the entire panel should be there
tester.clickLink("tabpanel:tabs-container:tabs:2:link");
- tester.assertContains("<span wicket:id=\"title\">added 1</span></a>");
+ tester.assertContains("<span wicket:id=\"title\">added 1</span>");
tester.assertContains("<span wicket:id=\"label\">added 1</span>");
assertEquals(Integer.valueOf(2), page.tabbedPanel.getDefaultModelObject());
}
-}
+
+ /**
+ * Changing model switches tab.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void renderModelChange() throws Exception
+ {
+ TestPage page = new TestPage();
+
+ tester.startPage(page);
+ tester.assertContains("<span wicket:id=\"label\">default 1</span>");
+
+ page.tabbedPanel.setDefaultModelObject(Integer.valueOf(1));
+ tester.startPage(page);
+
+ tester.assertContains("<span wicket:id=\"label\">default 2</span>");
+ }
+
+ /**
+ * Tab's component is aquired once only.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void tabComponentAquiredOnChangeOnly() throws Exception
+ {
+
+ final int[] count = new int[1];
+
+ TestPage page = new TestPage();
+ page.tabbedPanel.getTabs().clear();
+ page.tabbedPanel.getTabs().add(new AbstractTab(Model.of("added 1"))
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public WebMarkupContainer getPanel(String panelId)
+ {
+ count[0]++;
+
+ return new TestPanel(panelId, "added 1");
+ }
+ });
+
+ assertEquals(0, count[0]);
+ tester.startPage(page);
+ assertEquals(1, count[0]);
+ tester.startPage(page);
+ assertEquals(1, count[0]);
+
+ page.tabbedPanel.setSelectedTab(0);
+
+ assertEquals(2, count[0]);
+ tester.startPage(page);
+ assertEquals(2, count[0]);
+ }
+
+ /**
+ * An invisible tab gets replaced by another one.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void invisibleTabGetsReplaced() throws Exception
+ {
+ final boolean[] visible = { true, true };
+
+ TestPage page = new TestPage();
+ page.tabbedPanel.getTabs().clear();
+ page.tabbedPanel.getTabs().add(new AbstractTab(Model.of("added 1"))
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public WebMarkupContainer getPanel(String panelId)
+ {
+ return new TestPanel(panelId, "added 1");
+ }
+
+ @Override
+ public boolean isVisible()
+ {
+ return visible[0];
+ }
+ });
+ page.tabbedPanel.getTabs().add(new AbstractTab(Model.of("added 2"))
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public WebMarkupContainer getPanel(String panelId)
+ {
+ return new TestPanel(panelId, "added 2");
+ }
+
+ @Override
+ public boolean isVisible()
+ {
+ return visible[1];
+ }
+ });
+
+ page.tabbedPanel.setSelectedTab(1);
+
+ tester.startPage(page);
+
+ assertEquals(Integer.valueOf(1), page.tabbedPanel.getDefaultModelObject());
+ tester.assertContains("<span wicket:id=\"title\">added 1</span>");
+ tester.assertContains("<span wicket:id=\"title\">added 2</span>");
+ tester.assertContains("<span wicket:id=\"label\">added 2</span>");
+
+ visible[1] = false;
+
+ tester.startPage(page);
+
+ // now first tab is selected
+ assertEquals(Integer.valueOf(0), page.tabbedPanel.getDefaultModelObject());
+
+ tester.assertContains("<span wicket:id=\"title\">added 1</span>");
+ tester.assertContainsNot("<span wicket:id=\"title\">added 2</span>");
+ tester.assertContains("<span wicket:id=\"label\">added 1</span>");
+
+ visible[0] = false;
+
+ tester.startPage(page);
+
+ // first tab stays selected since no other is visible
+ assertEquals(Integer.valueOf(0), page.tabbedPanel.getDefaultModelObject());
+ tester.assertContainsNot("<span wicket:id=\"title\">added 1</span>");
+ tester.assertContainsNot("<span wicket:id=\"title\">added 2</span>");
+ tester.assertContains("<!-- no panel -->");
+
+ visible[1] = true;
+
+ tester.startPage(page);
+
+ // second selected again
+ assertEquals(Integer.valueOf(1), page.tabbedPanel.getDefaultModelObject());
+ tester.assertContainsNot("<span wicket:id=\"title\">added 1</span>");
+ tester.assertContains("<span wicket:id=\"title\">added 2</span>");
+ tester.assertContains("<span wicket:id=\"label\">added 2</span>");
+ }
+}
\ No newline at end of file