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());
        }
 }

Reply via email to