Updated Branches: refs/heads/master 02f5b9bf6 -> bf96810d0
WICKET-4593 TabbedPanel bi-directional model Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/bf96810d Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/bf96810d Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/bf96810d Branch: refs/heads/master Commit: bf96810d00d0eb916a0425dc413afef6f2fb5b57 Parents: 02f5b9b Author: Sven Meier <[email protected]> Authored: Wed Jun 6 17:56:06 2012 +0200 Committer: Sven Meier <[email protected]> Committed: Wed Jun 6 17:56:06 2012 +0200 ---------------------------------------------------------------------- .../wicket/examples/compref/TabbedPanelPage.html | 3 + .../wicket/examples/compref/TabbedPanelPage.java | 19 ++- .../extensions/markup/html/tabs/TabbedPanel.html | 2 +- .../extensions/markup/html/tabs/TabbedPanel.java | 124 ++++++++++++--- .../markup/html/tabs/TabbedPanelTest.java | 34 ++++- 5 files changed, 150 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/bf96810d/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.html ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.html index 76a57f4..b28afb5 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.html +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.html @@ -20,6 +20,9 @@ <p> <div wicket:id="tabs" class="tabpanel">[tabbed panel will be here]</div> </p> + <p> + <a wicket:id="skip">Skip to the next tab via model change.</a> + </p> <span wicket:id="explainPanel">panel contents come here</span> </body> </html> http://git-wip-us.apache.org/repos/asf/wicket/blob/bf96810d/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.java ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.java index 2262411..0e0c030 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/TabbedPanelPage.java @@ -52,7 +52,7 @@ public class TabbedPanelPage extends WicketExamplePage addCssSwitchingLinks(); // create a list of ITab objects used to feed the tabbed panel - List<ITab> tabs = new ArrayList<ITab>(); + final List<ITab> tabs = new ArrayList<ITab>(); tabs.add(new AbstractTab(new Model<String>("first tab")) { private static final long serialVersionUID = 1L; @@ -91,9 +91,22 @@ public class TabbedPanelPage extends WicketExamplePage // add the new tabbed panel, attribute modifier only used to switch // between different css variations - add(new TabbedPanel("tabs", tabs).add(AttributeModifier.replace("class", - TabbedPanelPage.this.getDefaultModel()))); + final TabbedPanel<ITab> tabbedPanel = new TabbedPanel<ITab>("tabs", tabs); + tabbedPanel.add(AttributeModifier.replace("class", TabbedPanelPage.this.getDefaultModel())); + add(tabbedPanel); + add(new Link<Void>("skip") + { + private static final long serialVersionUID = 1L; + + @Override + public void onClick() + { + int index = tabbedPanel.getModelObject(); + + tabbedPanel.setModelObject((index + 1) % tabs.size()); + } + }); } private void addCssSwitchingLinks() http://git-wip-us.apache.org/repos/asf/wicket/blob/bf96810d/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.html ---------------------------------------------------------------------- diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.html b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.html index 2ef03f5..0f3ebe0 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.html +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tabs/TabbedPanel.html @@ -23,5 +23,5 @@ </li> </ul> </div> -<div wicket:id="panel" class="tab-panel">[panel]</div> +<div wicket:id="panel" class="tab-panel"><!-- no panel --></div> </wicket:panel> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/wicket/blob/bf96810d/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..fa8ac71 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 @@ -37,9 +37,6 @@ import org.apache.wicket.util.lang.Args; * TabbedPanel component represets 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, - * the change is not picked up unless a call is made to {@link #setSelectedTab(int)}. - * <p> * Example: * * <pre> @@ -93,7 +90,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 selected tab index OR {@code -1} + */ + public TabbedPanel(final String id, final List<T> tabs, IModel<Integer> model) + { + super(id, model); this.tabs = Args.notNull(tabs, "tabs"); @@ -137,6 +149,61 @@ public class TabbedPanel<T extends ITab> extends Panel } /** + * Get the model. + * + * @return model + */ + @SuppressWarnings("unchecked") + public final IModel<Integer> getModel() + { + return (IModel<Integer>)getDefaultModel(); + } + + /** + * Get the model object. + * + * @return model object + */ + public final Integer getModelObject() + { + return getModel().getObject(); + } + + /** + * Set the model. + * + * @param model + */ + public final void setModel(IModel<Integer> model) + { + setDefaultModel(model); + } + + /** + * Set the model object. + * + * @param object + * model object + */ + public final void setModelObject(Integer object) + { + setDefaultModelObject(object); + } + + @Override + protected IModel<?> initModel() + { + IModel<?> model = super.initModel(); + + if (model == null) + { + model = new Model<Integer>(new Integer(-1)); + } + + return model; + } + + /** * Generates the container for all tabs. The default container automatically adds the css * <code>class</code> attribute based on the return value of {@link #getTabContainerCssClass()} * @@ -207,38 +274,37 @@ 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; + index = 0; for (int i = 0; i < tabs.size(); i++) { if (isTabVisible(i)) { - selected = i; + index = i; break; } } - if (selected == tabs.size()) + if (index == tabs.size()) { /* * 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 */ - selected = 0; + index = -1; + } + else + { + setModelObject(index); } - - setSelectedTab(selected); } + // updating the tab will do no harm if the index hasn't changed + updateTab(index); + super.onBeforeRender(); } @@ -331,18 +397,25 @@ public class TabbedPanel<T extends ITab> extends Panel * index of the tab to select * @return this for chaining */ - public TabbedPanel setSelectedTab(final int index) + public TabbedPanel<T> setSelectedTab(int index) { - if ((index < 0) || ((index >= tabs.size()) && (index > 0))) + if (index < 0 || index >= tabs.size()) { throw new IndexOutOfBoundsException(); } - setDefaultModelObject(index); + setModelObject(index); + + updateTab(index); + return this; + } + + private void updateTab(int index) + { final Component component; - if ((tabs.size() == 0) || !isTabVisible(index)) + if (index == -1 || !isTabVisible(index)) { // no tabs or the currently selected tab is not visible component = new WebMarkupContainer(TAB_PANEL_ID); @@ -350,12 +423,13 @@ public class TabbedPanel<T extends ITab> extends Panel else { // show panel from selected tab - T tab = tabs.get(index); + ITab tab = tabs.get(index); component = tab.getPanel(TAB_PANEL_ID); if (component == null) { throw new WicketRuntimeException("ITab.getPanel() returned null. TabbedPanel [" + getPath() + "] ITab index [" + index + "]"); + } } @@ -369,8 +443,6 @@ public class TabbedPanel<T extends ITab> extends Panel } addOrReplace(component); - - return this; } /** http://git-wip-us.apache.org/repos/asf/wicket/blob/bf96810d/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 397de15..9acbd13 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 @@ -27,6 +27,9 @@ import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.Model; import org.junit.Test; +/** + * Test for {@link TabbedPanel}. + */ public class TabbedPanelTest extends WicketTestCase { public class TestPage extends WebPage @@ -75,20 +78,41 @@ public class TabbedPanelTest extends WicketTestCase } @Test + public void renderNoTabs() throws Exception + { + TestPage page = new TestPage(); + page.tabbedPanel.getTabs().clear(); + tester.startPage(page); + + tester.assertContainsNot("<span wicket:id=\"title\">default 1</span></a>"); + tester.assertContainsNot("<span wicket:id=\"label\">default 1</span>"); + tester.assertContainsNot("<span wicket:id=\"title\">default 2</span></a>"); + tester.assertContainsNot("<span wicket:id=\"label\">default 2</span>"); + tester.assertContains("<!-- no panel -->"); + + assertEquals(Integer.valueOf(-1), page.tabbedPanel.getModelObject()); + } + + @Test public void renderDefaultTabsOnly() throws Exception { - tester.startPage(new TestPage()); + TestPage page = tester.startPage(new TestPage()); tester.assertContains("<span wicket:id=\"title\">default 1</span></a>"); tester.assertContains("<span wicket:id=\"label\">default 1</span>"); tester.assertContains("<span wicket:id=\"title\">default 2</span></a>"); + + assertEquals(Integer.valueOf(0), page.tabbedPanel.getModelObject()); + tester.clickLink("tabpanel:tabs-container:tabs:1:link"); tester.assertContains("<span wicket:id=\"label\">default 2</span>"); + + assertEquals(Integer.valueOf(1), page.tabbedPanel.getModelObject()); } @Test public void renderAdditionalTabs() throws Exception { - TestPage page = (TestPage)tester.startPage(new TestPage()); + TestPage page = tester.startPage(new TestPage()); page.tabbedPanel.getTabs().add(new AbstractTab(Model.of("added 1")) { @Override @@ -101,14 +125,20 @@ public class TabbedPanelTest extends WicketTestCase tester.assertContainsNot("<span wicket:id=\"title\">added 1</span></a>"); tester.assertContainsNot("<span wicket:id=\"label\">added 1</span>"); + assertEquals(Integer.valueOf(0), page.tabbedPanel.getModelObject()); + // 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.assertContainsNot("<span wicket:id=\"label\">added 1</span>"); + assertEquals(Integer.valueOf(1), page.tabbedPanel.getModelObject()); + // 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=\"label\">added 1</span>"); + + assertEquals(Integer.valueOf(2), page.tabbedPanel.getModelObject()); } }
