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/02/05 23:02:55 UTC

[3/9] git commit: moving old tree examples away, merged recursive panel example into panel compref

moving old tree examples away, merged recursive panel example into panel
compref


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/05840d1c
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/05840d1c
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/05840d1c

Branch: refs/heads/master
Commit: 05840d1c81cc3aff547e017b35a9106bb30af07e
Parents: cff7cfd 23e81bf
Author: Sven Meier <sv...@apache.org>
Authored: Thu Jan 26 17:41:04 2012 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sat Feb 4 19:04:40 2012 +0100

----------------------------------------------------------------------
 .../src/main/java/org/apache/wicket/Component.java |    8 +-
 .../java/org/apache/wicket/MarkupContainer.java    |    8 -
 .../html/panel/FragmentMarkupSourcingStrategy.java |    6 +-
 .../wicket/protocol/http/WebApplication.java       |    3 +-
 .../wicket/util/tester/BaseWicketTester.java       |    2 +-
 .../apache/wicket/examples/ajax/builtin/Index.html |    2 -
 .../examples/ajax/builtin/tree/BaseTreePage.java   |    8 +-
 .../ajax/builtin/tree/EditableTreeTablePage.java   |    1 +
 .../examples/ajax/builtin/tree/SimpleTreePage.java |    1 +
 .../examples/ajax/builtin/tree/TreeTablePage.java  |    1 +
 .../apache/wicket/examples/compref/MyPanel.html    |    7 +-
 .../apache/wicket/examples/compref/MyPanel.java    |   21 +
 .../apache/wicket/examples/compref/PanelPage.html  |    9 +-
 .../wicket/examples/compref/RecursivePanel.html    |   12 +
 .../wicket/examples/compref/RecursivePanel.java    |  112 +++++
 .../org/apache/wicket/examples/nested/Home.html    |   26 --
 .../org/apache/wicket/examples/nested/Home.java    |  150 -------
 .../wicket/examples/nested/NestedApplication.java  |   56 ---
 .../wicket/examples/nested/RecursivePanel.html     |   12 -
 .../wicket/examples/nested/RecursivePanel.java     |  112 -----
 .../java/org/apache/wicket/examples/tree/Foo.java  |  137 ++++++
 .../org/apache/wicket/examples/tree/FooPanel.html  |   51 +++
 .../org/apache/wicket/examples/tree/FooPanel.java  |   40 ++
 .../apache/wicket/examples/tree/FooProvider.java   |  129 ++++++
 .../wicket/examples/tree/NestedTreePage.html       |   38 ++
 .../wicket/examples/tree/NestedTreePage.java       |   51 +++
 .../apache/wicket/examples/tree/TableTreePage.html |   46 ++
 .../apache/wicket/examples/tree/TableTreePage.java |  108 +++++
 .../wicket/examples/tree/TreeApplication.java      |  134 ++++++
 .../org/apache/wicket/examples/tree/TreePage.html  |   57 +++
 .../org/apache/wicket/examples/tree/TreePage.java  |  236 ++++++++++
 .../wicket/examples/tree/TreePage.properties       |   15 +
 .../tree/content/BookmarkableFolderContent.java    |   77 ++++
 .../tree/content/CheckedFolderContent.java         |   96 ++++
 .../content/CheckedSelectableFolderContent.java    |   90 ++++
 .../wicket/examples/tree/content/Content.java      |   45 ++
 .../tree/content/EditableFolderContent.java        |   91 ++++
 .../examples/tree/content/FolderContent.java       |   38 ++
 .../wicket/examples/tree/content/LabelContent.java |   38 ++
 .../wicket/examples/tree/content/MixedContent.java |   49 ++
 .../tree/content/MultiLineLabelContent.java        |   49 ++
 .../tree/content/MultiSelectableFolderContent.java |   97 ++++
 .../wicket/examples/tree/content/PanelContent.java |   38 ++
 .../tree/content/SelectableFolderContent.java      |  111 +++++
 .../apache/wicket/examples/homepage/HomePage.html  |    2 +-
 wicket-examples/src/main/webapp/WEB-INF/web.xml    |   32 +-
 wicket-examples/src/main/webapp/style.css          |    5 +
 .../markup/html/repeater/data/table/DataTable.java |   12 +-
 .../markup/html/repeater/tree/AbstractTree.java    |  343 +++++++++++++++
 .../html/repeater/tree/DefaultNestedTree.java      |   55 +++
 .../html/repeater/tree/DefaultTableTree.java       |   75 ++++
 .../html/repeater/tree/ISortableTreeProvider.java  |   30 ++
 .../markup/html/repeater/tree/ITreeProvider.java   |   78 ++++
 .../markup/html/repeater/tree/NestedTree.html      |   20 +
 .../markup/html/repeater/tree/NestedTree.java      |  122 +++++
 .../extensions/markup/html/repeater/tree/Node.html |   27 ++
 .../extensions/markup/html/repeater/tree/Node.java |  213 +++++++++
 .../markup/html/repeater/tree/TableTree.html       |   20 +
 .../markup/html/repeater/tree/TableTree.java       |  226 ++++++++++
 .../html/repeater/tree/content/CheckFolder.html    |   35 ++
 .../html/repeater/tree/content/CheckFolder.java    |   40 ++
 .../html/repeater/tree/content/CheckedFolder.html  |   35 ++
 .../html/repeater/tree/content/CheckedFolder.java  |   92 ++++
 .../markup/html/repeater/tree/content/Folder.java  |  157 +++++++
 .../repeater/tree/content/StyledLinkLabel.html     |   33 ++
 .../repeater/tree/content/StyledLinkLabel.java     |  166 +++++++
 .../html/repeater/tree/nested/BranchItem.java      |   61 +++
 .../markup/html/repeater/tree/nested/Subtree.html  |   34 ++
 .../markup/html/repeater/tree/nested/Subtree.java  |  171 +++++++
 .../repeater/tree/table/AbstractTreeColumn.java    |   50 +++
 .../html/repeater/tree/table/ITreeColumn.java      |   28 ++
 .../repeater/tree/table/ITreeDataProvider.java     |   34 ++
 .../html/repeater/tree/table/NodeBorder.java       |   85 ++++
 .../markup/html/repeater/tree/table/NodeModel.java |   96 ++++
 .../html/repeater/tree/table/TreeColumn.java       |   61 +++
 .../html/repeater/tree/table/TreeDataProvider.java |  194 ++++++++
 .../html/repeater/tree/theme/HumanTheme.java       |   48 ++
 .../html/repeater/tree/theme/WindowsTheme.java     |   48 ++
 .../repeater/tree/theme/human/folder-other.gif     |  Bin 0 -> 1069 bytes
 .../html/repeater/tree/theme/human/folder.gif      |  Bin 0 -> 579 bytes
 .../html/repeater/tree/theme/human/theme.css       |  126 ++++++
 .../markup/html/repeater/tree/theme/human/tree.gif |  Bin 0 -> 213 bytes
 .../repeater/tree/theme/windows/folder-closed.gif  |  Bin 0 -> 372 bytes
 .../repeater/tree/theme/windows/folder-open.gif    |  Bin 0 -> 376 bytes
 .../repeater/tree/theme/windows/folder-other.gif   |  Bin 0 -> 582 bytes
 .../html/repeater/tree/theme/windows/theme.css     |  126 ++++++
 .../html/repeater/tree/theme/windows/tree.gif      |  Bin 0 -> 3747 bytes
 .../markup/html/repeater/tree/util/InverseSet.java |  143 ++++++
 .../markup/html/repeater/tree/util/KeyingSet.java  |  164 +++++++
 .../html/repeater/tree/util/ProviderSubset.java    |  242 ++++++++++
 .../repeater/tree/util/SortableTreeProvider.java   |   97 ++++
 .../html/repeater/tree/util/TreeModelProvider.java |  258 +++++++++++
 .../html/repeater/tree/table/NodeModelTest.java    |   87 ++++
 .../repeater/tree/table/TreeDataProviderTest.java  |  128 ++++++
 .../html/repeater/tree/util/InverseSetTest.java    |   77 ++++
 .../repeater/tree/util/ProviderSubsetTest.java     |  170 +++++++
 .../repeater/tree/util/TreeModelProviderTest.java  |  155 +++++++
 .../injection/CompoundFieldValueFactory.java       |   30 +-
 98 files changed, 6517 insertions(+), 432 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/Index.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/Index.html
index 4fa3e3e,4fa3e3e..5c0c38c
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/Index.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/Index.html
@@@ -30,8 -30,8 +30,6 @@@
  <br/><br/>
  <a href="RatingsPage.html">Ratings example</a>: shows a rating component.
  <br/><br/>
--<a href="tree/SimpleTreePage.html">Tree and TreeTable</a>: shows ajax tree and ajax tree table.
--<br/><br/>
  <a href="TabbedPanelPage.html">Tabbed Panel Example</a>: demonstrates ajax enabled tabbed panel
  <br/><br/>
  <a href="TodoList.html">Todo list Example</a>: shows ajax todo list page without writing any JavaScript

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/BaseTreePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/BaseTreePage.java
index 0a9a324,16eb34d..eb749f0
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/BaseTreePage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/BaseTreePage.java
@@@ -17,7 -17,7 +17,6 @@@
  package org.apache.wicket.examples.ajax.builtin.tree;
  
  import java.util.ArrayList;
--import java.util.Iterator;
  import java.util.List;
  
  import javax.swing.tree.DefaultMutableTreeNode;
@@@ -35,6 -35,6 +34,7 @@@ import org.apache.wicket.extensions.mar
   * 
   * @author Matej Knopp
   */
++@Deprecated
  public abstract class BaseTreePage extends BasePage
  {
  
@@@ -146,14 -146,14 +146,14 @@@
  			if (obj instanceof List)
  			{
  				DefaultMutableTreeNode child = new DefaultMutableTreeNode(new ModelBean(
--						"subtree..."));
++					"subtree..."));
  				parent.add(child);
--				add(child, (List<Object>) obj);
++				add(child, (List<Object>)obj);
  			}
  			else
  			{
  				DefaultMutableTreeNode child = new DefaultMutableTreeNode(new ModelBean(
--						obj.toString()));
++					obj.toString()));
  				parent.add(child);
  			}
  		}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/EditableTreeTablePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/EditableTreeTablePage.java
index 1f9baed,80a030e..863adcd
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/EditableTreeTablePage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/EditableTreeTablePage.java
@@@ -31,6 -31,6 +31,7 @@@ import org.apache.wicket.markup.html.fo
   * 
   * @author Matej Knopp
   */
++@Deprecated
  public class EditableTreeTablePage extends BaseTreePage
  {
  	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/SimpleTreePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/SimpleTreePage.java
index 4a2a932,d87d63c..e4a97a6
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/SimpleTreePage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/SimpleTreePage.java
@@@ -27,6 -27,6 +27,7 @@@ import org.apache.wicket.extensions.mar
   * @author Matej
   * 
   */
++@Deprecated
  public class SimpleTreePage extends BaseTreePage
  {
  	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/TreeTablePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/TreeTablePage.java
index 79f33da,0a78534..690a1c0
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/TreeTablePage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/tree/TreeTablePage.java
@@@ -30,6 -30,6 +30,7 @@@ import org.apache.wicket.extensions.mar
   * 
   * @author Matej Knopp
   */
++@Deprecated
  public class TreeTablePage extends BaseTreePage
  {
  	private static final long serialVersionUID = 1L;

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.html
index 1ec2ae5,1ec2ae5..6ee9e06
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.html
@@@ -11,14 -11,14 +11,15 @@@
   
   <wicket:panel>
   
-- 	<p style="border: 2px dotted #fc0; padding: 5px;">
++ 	<p class="panel">
   	 Here are some panel contents for ya.<br />
   	 Put arbitrairy Wicket components in your Panels,
   	 like this label: <span wicket:id="label" class="mark">to be replaced</span>, or<br />
   	 even another panel: <span wicket:id="otherPanel"  class="mark">also to be replaced</span>.<br />
-- 	 You can nest panels any deep you want.
++ 	 You can nest panels any deep you want:
   	</p>
-- 
++ 	
++ 	<div wicket:id="recursive" class="panel"></div>
   </wicket:panel>
  
  </body>

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.java
index ab9bd72,ab9bd72..2cdba26
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/MyPanel.java
@@@ -16,6 -16,6 +16,9 @@@
   */
  package org.apache.wicket.examples.compref;
  
++import java.util.ArrayList;
++import java.util.List;
++
  import org.apache.wicket.markup.html.basic.Label;
  import org.apache.wicket.markup.html.panel.Panel;
  
@@@ -37,5 -37,5 +40,23 @@@ class MyPanel extends Pane
  		super(id);
  		add(new Label("label", "yep, this is from a component proper"));
  		add(new AnotherPanel("otherPanel"));
++
++		// create a list with sublists
++		List<Object> l1 = new ArrayList<Object>();
++		l1.add("test 1.1");
++		l1.add("test 1.2");
++		List<Object> l2 = new ArrayList<Object>();
++		l2.add("test 2.1");
++		l2.add("test 2.2");
++		l2.add("test 2.3");
++		List<String> l3 = new ArrayList<String>();
++		l3.add("test 3.1");
++		l2.add(l3);
++		l2.add("test 2.4");
++		l1.add(l2);
++		l1.add("test 1.3");
++
++		// construct the panel
++		add(new RecursivePanel("recursive", l1));
  	}
  }

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/compref/PanelPage.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/compref/PanelPage.html
index a25accd,a25accd..3cd922c
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/compref/PanelPage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/PanelPage.html
@@@ -11,11 -11,11 +11,12 @@@
  	<wicket:link><a href="Index.html">[back to the reference]</a></wicket:link>
  
  	<p>
--	Use panels to group markup and components.<br />
--
--	<span wicket:id="panel">panel contents come here</span>
++	Use panels to group markup and components.
  	</p>
--    <span wicket:id="explainPanel">panel contents come here</span>
++
++	<div wicket:id="panel">panel contents come here</div>
++	
++    <div wicket:id="explainPanel">panel contents come here</div>
  
  </body>
  </html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.html
index 0000000,0000000..28d2f7d
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.html
@@@ -1,0 -1,0 +1,12 @@@
++<html xmlns:wicket="http://wicket.apache.org">
++<wicket:panel>
++  <ul>
++    <span wicket:id="rows">
++      <li wicket:id="row">
++        <span wicket:id="label">the label</span>
++      </li>
++      <span wicket:id="nested"/>
++    </span>
++  </ul>
++</wicket:panel>
++</html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.java
index 0000000,0000000..05f6feb
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/compref/RecursivePanel.java
@@@ -1,0 -1,0 +1,112 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.compref;
++
++import java.util.List;
++
++import org.apache.wicket.markup.html.WebMarkupContainer;
++import org.apache.wicket.markup.html.basic.Label;
++import org.apache.wicket.markup.html.list.ListItem;
++import org.apache.wicket.markup.html.list.ListView;
++import org.apache.wicket.markup.html.panel.Panel;
++
++
++/**
++ * This example list knows how to display sublists. It expects a list where each element is either a
++ * string or another list.
++ * 
++ * @author Eelco Hillenius
++ */
++public final class RecursivePanel extends Panel
++{
++	/**
++	 * Constructor.
++	 * 
++	 * @param id
++	 *            The id of this component
++	 * @param list
++	 *            a list where each element is either a string or another list
++	 */
++	public RecursivePanel(final String id, List<Object> list)
++	{
++		super(id);
++		add(new Rows("rows", list));
++		setVersioned(false);
++	}
++
++	/**
++	 * The list class.
++	 */
++	private static class Rows extends ListView<Object>
++	{
++		/**
++		 * Construct.
++		 * 
++		 * @param name
++		 *            name of the component
++		 * @param list
++		 *            a list where each element is either a string or another list
++		 */
++		public Rows(String name, List<Object> list)
++		{
++			super(name, list);
++		}
++
++		/**
++		 * @see org.apache.wicket.markup.html.list.ListView#populateItem(org.apache.wicket.markup.html.list.ListItem)
++		 */
++		@SuppressWarnings("unchecked")
++		@Override
++		protected void populateItem(ListItem<Object> listItem)
++		{
++			Object modelObject = listItem.getDefaultModelObject();
++
++			if (modelObject instanceof List)
++			{
++				// create a panel that renders the sub list
++				RecursivePanel nested = new RecursivePanel("nested", (List<Object>)modelObject);
++				listItem.add(nested);
++				// if the current element is a list, we create a dummy row/
++				// label element
++				// as we have to confirm to our HTML definition, and set it's
++				// visibility
++				// property to false as we do not want LI tags to be rendered.
++				WebMarkupContainer row = new WebMarkupContainer("row");
++				row.setVisible(false);
++				row.add(new WebMarkupContainer("label"));
++				listItem.add(row);
++			}
++			else
++			{
++				// if the current element is not a list, we create a dummy panel
++				// element
++				// to confirm to our HTML definition, and set this panel's
++				// visibility
++				// property to false to avoid having the UL tag rendered
++				RecursivePanel nested = new RecursivePanel("nested", null);
++				nested.setVisible(false);
++				listItem.add(nested);
++				// add the row (with the LI element attached, and the label with
++				// the
++				// row's actual value to display
++				WebMarkupContainer row = new WebMarkupContainer("row");
++				row.add(new Label("label", modelObject.toString()));
++				listItem.add(row);
++			}
++		}
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.html
index ee1103b,ee1103b..0000000
deleted file mode 100644,100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.html
+++ /dev/null

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.java
index 54acfab,bcb871c..0000000
deleted file mode 100644,100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/nested/Home.java
+++ /dev/null

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/nested/NestedApplication.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/nested/NestedApplication.java
index 2465109,2465109..0000000
deleted file mode 100644,100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/nested/NestedApplication.java
+++ /dev/null

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.html
index 28d2f7d,28d2f7d..0000000
deleted file mode 100644,100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.html
+++ /dev/null

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.java
index 324d565,324d565..0000000
deleted file mode 100644,100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/nested/RecursivePanel.java
+++ /dev/null

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/Foo.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/Foo.java
index 0000000,0000000..77b3bd8
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/Foo.java
@@@ -1,0 -1,0 +1,137 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.util.ArrayList;
++import java.util.Collections;
++import java.util.List;
++
++/**
++ * @author Sven Meier
++ */
++public class Foo
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private String id;
++
++	private String bar;
++
++	private String baz;
++
++	private boolean quux;
++
++	private boolean loaded;
++
++	private Foo parent;
++
++	private List<Foo> foos = new ArrayList<Foo>();
++
++	public Foo(String id)
++	{
++		this.id = id;
++		bar = id.toLowerCase() + "Bar";
++		baz = id.toLowerCase() + "Baz";
++	}
++
++	public Foo(Foo parent, String name)
++	{
++		this(name);
++
++		this.parent = parent;
++		this.parent.foos.add(this);
++	}
++
++	public Foo getParent()
++	{
++		return parent;
++	}
++
++	public String getId()
++	{
++		return id;
++	}
++
++	public String getBar()
++	{
++		return bar;
++	}
++
++	public String getBaz()
++	{
++		return baz;
++	}
++
++	public void setBar(String bar)
++	{
++		this.bar = bar;
++	}
++
++	public void setBaz(String baz)
++	{
++		this.baz = baz;
++	}
++
++	public void setQuux(boolean quux)
++	{
++		this.quux = quux;
++
++		if (quux)
++		{
++			// set quux on all descendants
++			for (Foo foo : foos)
++			{
++				foo.setQuux(true);
++			}
++		}
++		else
++		{
++			// clear quux on all ancestors
++			if (parent != null)
++			{
++				parent.setQuux(false);
++			}
++		}
++	}
++
++	public boolean getQuux()
++	{
++		return quux;
++	}
++
++	public List<Foo> getFoos()
++	{
++		return Collections.unmodifiableList(foos);
++	}
++
++	@Override
++	public String toString()
++	{
++		return id;
++	}
++
++	public boolean isLoaded()
++	{
++		return loaded;
++	}
++
++	public void setLoaded(boolean loaded)
++	{
++		this.loaded = loaded;
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.html
index 0000000,0000000..7e3b31a
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.html
@@@ -1,0 -1,0 +1,51 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<!--
++   Licensed to the Apache Software Foundation (ASF) under one or more
++   contributor license agreements.  See the NOTICE file distributed with
++   this work for additional information regarding copyright ownership.
++   The ASF licenses this file to You 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.
++-->
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" >
++    <head>  
++    	<wicket:head>
++<style>
++div.foo-outer {
++  margin-bottom: 4px;
++  border: 1px dotted black;
++  padding-left: 18px;
++  background-color: #BBBBBB;
++}
++
++div.foo-inner {
++  padding: 2px;
++  background-color: #FFFFFF;
++}
++</style>
++    	</wicket:head>
++    </head>
++    <body>
++		<wicket:panel>
++			<div class="foo-outer">
++				<div class="foo-inner">
++					Bar <input type="text" wicket:id="bar"/>
++					<br/>
++					Baz <input type="text" wicket:id="baz"/>
++					<br/>
++					Quux <input type="checkbox" wicket:id="quux"/>
++				</div>
++			</div>
++		</wicket:panel>
++    </body>
++</html>
++

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.java
index 0000000,0000000..46308d5
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooPanel.java
@@@ -1,0 -1,0 +1,40 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import org.apache.wicket.markup.html.form.CheckBox;
++import org.apache.wicket.markup.html.form.TextField;
++import org.apache.wicket.markup.html.panel.Panel;
++import org.apache.wicket.model.CompoundPropertyModel;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class FooPanel extends Panel
++{
++	private static final long serialVersionUID = 1L;
++
++	public FooPanel(String id, IModel<Foo> foo)
++	{
++		super(id, new CompoundPropertyModel<Foo>(foo));
++
++		add(new TextField<String>("bar"));
++		add(new TextField<String>("baz"));
++		add(new CheckBox("quux"));
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooProvider.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooProvider.java
index 0000000,0000000..4fc13bb
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/FooProvider.java
@@@ -1,0 -1,0 +1,129 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.io.Serializable;
++import java.util.Iterator;
++
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.model.LoadableDetachableModel;
++import org.apache.wicket.model.Model;
++
++/**
++ * A provider of {@link Foo}s.
++ * 
++ * For simplicity all foos are kept as class members, in a real world scenario these would be
++ * fetched from a database. If {@link Foo}s were {@link Serializable} you could of course just keep
++ * references in instance variables.
++ * 
++ * @see #model(Foo)
++ * 
++ * @author Sven Meier
++ */
++public class FooProvider implements ITreeProvider<Foo>
++{
++
++	private static final long serialVersionUID = 1L;
++
++	/**
++	 * Construct.
++	 */
++	public FooProvider()
++	{
++	}
++
++	/**
++	 * Nothing to do.
++	 */
++	public void detach()
++	{
++	}
++
++	public Iterator<Foo> getRoots()
++	{
++		return TreeApplication.get().foos.iterator();
++	}
++
++	public boolean hasChildren(Foo foo)
++	{
++		return foo.getParent() == null || !foo.getFoos().isEmpty();
++	}
++
++	public Iterator<Foo> getChildren(final Foo foo)
++	{
++		return foo.getFoos().iterator();
++	}
++
++	/**
++	 * Creates a {@link FooModel}.
++	 */
++	public IModel<Foo> model(Foo foo)
++	{
++		return new FooModel(foo);
++	}
++
++	/**
++	 * A {@link Model} which uses an id to load its {@link Foo}.
++	 * 
++	 * If {@link Foo}s were {@link Serializable} you could just use a standard {@link Model}.
++	 * 
++	 * @see #equals(Object)
++	 * @see #hashCode()
++	 */
++	private static class FooModel extends LoadableDetachableModel<Foo>
++	{
++		private static final long serialVersionUID = 1L;
++
++		private String id;
++
++		public FooModel(Foo foo)
++		{
++			super(foo);
++
++			id = foo.getId();
++		}
++
++		@Override
++		protected Foo load()
++		{
++			return TreeApplication.get().getFoo(id);
++		}
++
++		/**
++		 * Important! Models must be identifyable by their contained object.
++		 */
++		@Override
++		public boolean equals(Object obj)
++		{
++			if (obj instanceof FooModel)
++			{
++				return ((FooModel)obj).id.equals(id);
++			}
++			return false;
++		}
++
++		/**
++		 * Important! Models must be identifyable by their contained object.
++		 */
++		@Override
++		public int hashCode()
++		{
++			return id.hashCode();
++		}
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.html
index 0000000,0000000..1b8a840
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.html
@@@ -1,0 -1,0 +1,38 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<!--
++   Licensed to the Apache Software Foundation (ASF) under one or more
++   contributor license agreements.  See the NOTICE file distributed with
++   this work for additional information regarding copyright ownership.
++   The ASF licenses this file to You 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.
++-->
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" >
++    <head>
++    	<wicket:head>
++<style>
++ul.tree {
++	width: 480px;
++	height: 240px;
++	overflow: auto;
++	border: 1px solid #DDDDDD;
++}
++</style>
++    	</wicket:head>
++    </head>
++    <body>
++    	<wicket:extend>
++			<div wicket:id="tree">[tree]</div>
++    	</wicket:extend>
++    </body>
++</html>
++

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.java
index 0000000,0000000..e5fbfc5
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/NestedTreePage.java
@@@ -1,0 -1,0 +1,51 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.util.Set;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class NestedTreePage extends TreePage
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private NestedTree<Foo> tree;
++
++	@Override
++	protected AbstractTree<Foo> createTree(FooProvider provider, IModel<Set<Foo>> state)
++	{
++		tree = new NestedTree<Foo>("tree", provider, state)
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected Component newContentComponent(String id, IModel<Foo> model)
++			{
++				return NestedTreePage.this.newContentComponent(id, model);
++			}
++		};
++		return tree;
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.html
index 0000000,0000000..f70f383
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.html
@@@ -1,0 -1,0 +1,46 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<!--
++   Licensed to the Apache Software Foundation (ASF) under one or more
++   contributor license agreements.  See the NOTICE file distributed with
++   this work for additional information regarding copyright ownership.
++   The ASF licenses this file to You 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.
++-->
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" >
++    <head>
++    	<wicket:head>
++<style>
++table {
++	width: 100%;
++	border: 1px solid #DDDDDD;
++}
++tr.even {
++	background-color: #FFFFFF;
++}
++tr.odd {
++	background-color: #EEEEEE;
++}
++td.number {
++	text-align: right;
++	padding-right: 1em;
++}
++</style>
++    	</wicket:head>
++    </head>
++    <body>
++    	<wicket:extend>
++			<div wicket:id="tree">[tree]</div>
++    	</wicket:extend>
++    </body>
++</html>
++

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.java
index 0000000,0000000..52ff5d9
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TableTreePage.java
@@@ -1,0 -1,0 +1,108 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.util.ArrayList;
++import java.util.List;
++import java.util.Set;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.HeadersToolbar;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.TableTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.table.NodeModel;
++import org.apache.wicket.extensions.markup.html.repeater.tree.table.TreeColumn;
++import org.apache.wicket.markup.html.basic.Label;
++import org.apache.wicket.markup.repeater.Item;
++import org.apache.wicket.markup.repeater.OddEvenItem;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.model.Model;
++
++/**
++ * @author Sven Meier
++ */
++public class TableTreePage extends TreePage
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private TableTree<Foo> tree;
++
++	@Override
++	protected AbstractTree<Foo> createTree(FooProvider provider, IModel<Set<Foo>> state)
++	{
++		List<IColumn<Foo>> columns = createColumns();
++
++		tree = new TableTree<Foo>("tree", columns, provider, Integer.MAX_VALUE, state)
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected Component newContentComponent(String id, IModel<Foo> model)
++			{
++				return TableTreePage.this.newContentComponent(id, model);
++			}
++
++			@Override
++			protected Item<Foo> newRowItem(String id, int index, IModel<Foo> model)
++			{
++				return new OddEvenItem<Foo>(id, index, model);
++			}
++		};
++		tree.getTable().addTopToolbar(new HeadersToolbar(tree.getTable(), null));
++		tree.getTable().addBottomToolbar(new NoRecordsToolbar(tree.getTable()));
++		return tree;
++	}
++
++	private List<IColumn<Foo>> createColumns()
++	{
++		List<IColumn<Foo>> columns = new ArrayList<IColumn<Foo>>();
++
++		columns.add(new PropertyColumn<Foo>(Model.of("ID"), "id"));
++
++		columns.add(new TreeColumn<Foo>(Model.of("Tree")));
++
++		columns.add(new AbstractColumn<Foo>(Model.of("Depth"))
++		{
++			private static final long serialVersionUID = 1L;
++
++			public void populateItem(Item<ICellPopulator<Foo>> cellItem, String componentId,
++				IModel<Foo> rowModel)
++			{
++				NodeModel<Foo> nodeModel = (NodeModel<Foo>)rowModel;
++
++				cellItem.add(new Label(componentId, "" + nodeModel.getDepth()));
++			}
++
++			@Override
++			public String getCssClass()
++			{
++				return "number";
++			}
++		});
++
++		columns.add(new PropertyColumn<Foo>(Model.of("Bar"), "bar"));
++		columns.add(new PropertyColumn<Foo>(Model.of("Baz"), "baz"));
++
++		return columns;
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreeApplication.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreeApplication.java
index 0000000,0000000..f98c7ed
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreeApplication.java
@@@ -1,0 -1,0 +1,134 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.util.ArrayList;
++import java.util.List;
++
++import org.apache.wicket.Page;
++import org.apache.wicket.protocol.http.WebApplication;
++import org.apache.wicket.response.filter.ServerAndClientTimeFilter;
++
++/**
++ * Application class for tree examples.
++ * 
++ * @author svenmeier
++ */
++public class TreeApplication extends WebApplication
++{
++	/**
++	 * All root {@link Foo}s.
++	 */
++	public List<Foo> foos = new ArrayList<Foo>();
++
++	/**
++	 * Constructor.
++	 */
++	public TreeApplication()
++	{
++		Foo fooA = new Foo("A");
++		{
++			Foo fooAA = new Foo(fooA, "AA");
++			{
++				new Foo(fooAA, "AAA");
++				new Foo(fooAA, "AAB");
++			}
++			Foo fooAB = new Foo(fooA, "AB");
++			{
++				new Foo(fooAB, "ABA");
++				Foo fooABB = new Foo(fooAB, "ABB");
++				{
++					new Foo(fooABB, "ABBA");
++					Foo fooABBB = new Foo(fooABB, "ABBB");
++					{
++						new Foo(fooABBB, "ABBBA");
++					}
++				}
++				new Foo(fooAB, "ABC");
++				new Foo(fooAB, "ABD");
++			}
++			Foo fooAC = new Foo(fooA, "AC");
++			{
++				new Foo(fooAC, "ACA");
++				new Foo(fooAC, "ACB");
++			}
++		}
++		foos.add(fooA);
++
++		Foo fooB = new Foo("B");
++		{
++			new Foo(fooB, "BA");
++			new Foo(fooB, "BB");
++		}
++		foos.add(fooB);
++
++		Foo fooC = new Foo("C");
++		foos.add(fooC);
++	}
++
++	/**
++	 * @see org.apache.wicket.protocol.http.WebApplication#init()
++	 */
++	@Override
++	protected void init()
++	{
++		getDebugSettings().setDevelopmentUtilitiesEnabled(true);
++
++		getRequestCycleSettings().addResponseFilter(new ServerAndClientTimeFilter());
++	}
++
++	/**
++	 * @see org.apache.wicket.Application#getHomePage()
++	 */
++	@Override
++	public Class<? extends Page> getHomePage()
++	{
++		return NestedTreePage.class;
++	}
++
++	/**
++	 * Get a {@link Foo} by its id.
++	 */
++	public Foo getFoo(String id)
++	{
++		return findFoo(foos, id);
++	}
++
++	private static Foo findFoo(List<Foo> foos, String id)
++	{
++		for (Foo foo : foos)
++		{
++			if (foo.getId().equals(id))
++			{
++				return foo;
++			}
++
++			Foo temp = findFoo(foo.getFoos(), id);
++			if (temp != null)
++			{
++				return temp;
++			}
++		}
++
++		return null;
++	}
++
++	public static TreeApplication get()
++	{
++		return (TreeApplication)WebApplication.get();
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.html
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.html
index 0000000,0000000..82c6e3f
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.html
@@@ -1,0 -1,0 +1,57 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<!--
++   Licensed to the Apache Software Foundation (ASF) under one or more
++   contributor license agreements.  See the NOTICE file distributed with
++   this work for additional information regarding copyright ownership.
++   The ASF licenses this file to You 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.
++-->
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
++<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" >
++    <head>  
++	    <title>Wicket Examples - trees</title>
++	    <link rel="stylesheet" type="text/css" href="style.css"/>
++		<style>
++			.tree p {
++			  margin: 0px;
++			}
++		</style>
++    </head>
++    <body>
++	    <span wicket:id = "mainNavigation"/>
++	    
++	    <h2>Welcome to Tree Examples</h2>
++
++		<wicket:link>
++			<a href="NestedTreePage.html">NestedTee</a>
++			<a href="TableTreePage.html">TableTree</a>
++		</wicket:link>
++			
++		<form wicket:id="form">
++			<p>
++				Content: <select wicket:id="content"></select>
++			</p>
++			<p>
++				Theme: <select wicket:id="theme"></select>
++			</p>
++			<p>
++				<a wicket:id="collapseAll">collapse all</a>  <a wicket:id="expandAll">expand all</a>
++			</p>
++			<p>
++				<wicket:child/>
++			</p>
++			
++			<input type="submit" wicket:id="submit" value="OK"/>
++		</form>
++    </body>
++</html>
++

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.java
index 0000000,0000000..eb5b9f8
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.java
@@@ -1,0 -1,0 +1,236 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree;
++
++import java.util.ArrayList;
++import java.util.List;
++import java.util.Set;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.behavior.Behavior;
++import org.apache.wicket.examples.WicketExamplePage;
++import org.apache.wicket.examples.tree.content.BookmarkableFolderContent;
++import org.apache.wicket.examples.tree.content.CheckedFolderContent;
++import org.apache.wicket.examples.tree.content.CheckedSelectableFolderContent;
++import org.apache.wicket.examples.tree.content.Content;
++import org.apache.wicket.examples.tree.content.EditableFolderContent;
++import org.apache.wicket.examples.tree.content.FolderContent;
++import org.apache.wicket.examples.tree.content.LabelContent;
++import org.apache.wicket.examples.tree.content.MixedContent;
++import org.apache.wicket.examples.tree.content.MultiLineLabelContent;
++import org.apache.wicket.examples.tree.content.MultiSelectableFolderContent;
++import org.apache.wicket.examples.tree.content.PanelContent;
++import org.apache.wicket.examples.tree.content.SelectableFolderContent;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.theme.HumanTheme;
++import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme;
++import org.apache.wicket.extensions.markup.html.repeater.tree.util.InverseSet;
++import org.apache.wicket.extensions.markup.html.repeater.tree.util.ProviderSubset;
++import org.apache.wicket.markup.ComponentTag;
++import org.apache.wicket.markup.head.IHeaderResponse;
++import org.apache.wicket.markup.html.form.Button;
++import org.apache.wicket.markup.html.form.ChoiceRenderer;
++import org.apache.wicket.markup.html.form.DropDownChoice;
++import org.apache.wicket.markup.html.form.Form;
++import org.apache.wicket.markup.html.link.Link;
++import org.apache.wicket.model.AbstractReadOnlyModel;
++import org.apache.wicket.model.IDetachable;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.model.PropertyModel;
++
++/**
++ * @author Sven Meier
++ */
++public abstract class TreePage extends WicketExamplePage
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private Behavior theme;
++
++	private AbstractTree<Foo> tree;
++
++	private FooProvider provider = new FooProvider();
++
++	private Set<Foo> state = new ProviderSubset<Foo>(provider);
++
++	private Content content;
++
++	private List<Content> contents;
++
++	private List<Behavior> themes;
++
++	/**
++	 * Construct.
++	 */
++	public TreePage()
++	{
++		content = new CheckedFolderContent(provider);
++
++		Form<Void> form = new Form<Void>("form");
++		add(form);
++
++		tree = createTree(provider, newStateModel());
++		tree.add(new Behavior()
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			public void onComponentTag(Component component, ComponentTag tag)
++			{
++				theme.onComponentTag(component, tag);
++			}
++
++			@Override
++			public void renderHead(Component component, IHeaderResponse response)
++			{
++				theme.renderHead(component, response);
++			}
++		});
++		form.add(tree);
++
++		form.add(new DropDownChoice<Content>("content",
++			new PropertyModel<Content>(this, "content"), initContents(),
++			new ChoiceRenderer<Content>("class.simpleName"))
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected boolean wantOnSelectionChangedNotifications()
++			{
++				return true;
++			}
++		});
++
++		form.add(new DropDownChoice<Behavior>("theme", new PropertyModel<Behavior>(this, "theme"),
++			initThemes(), new ChoiceRenderer<Behavior>("class.simpleName"))
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected boolean wantOnSelectionChangedNotifications()
++			{
++				return true;
++			}
++		});
++
++		form.add(new Link<Void>("expandAll")
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			public void onClick()
++			{
++				((IDetachable)state).detach();
++				state = new InverseSet<Foo>(new ProviderSubset<Foo>(provider));
++			}
++		});
++
++		form.add(new Link<Void>("collapseAll")
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			public void onClick()
++			{
++				((IDetachable)state).detach();
++				state = new ProviderSubset<Foo>(provider);
++			}
++		});
++
++		form.add(new Button("submit")
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			public void onSubmit()
++			{
++			}
++		});
++	}
++
++	private IModel<Set<Foo>> newStateModel()
++	{
++		return new AbstractReadOnlyModel<Set<Foo>>()
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			public Set<Foo> getObject()
++			{
++				return state;
++			}
++
++			@Override
++			public void detach()
++			{
++				((IDetachable)state).detach();
++			}
++		};
++	}
++
++	protected abstract AbstractTree<Foo> createTree(FooProvider provider, IModel<Set<Foo>> state);
++
++	private List<Content> initContents()
++	{
++		contents = new ArrayList<Content>();
++
++		contents.add(new BookmarkableFolderContent(tree));
++		contents.add(new LabelContent());
++		contents.add(new MultiLineLabelContent());
++		contents.add(new FolderContent());
++		contents.add(new EditableFolderContent());
++		contents.add(new SelectableFolderContent(provider));
++		contents.add(new MultiSelectableFolderContent(provider));
++		contents.add(new CheckedFolderContent(provider));
++		contents.add(new CheckedSelectableFolderContent(provider));
++		contents.add(new PanelContent());
++		contents.add(new MixedContent(contents));
++
++		content = contents.get(0);
++
++		return contents;
++	}
++
++	private List<Behavior> initThemes()
++	{
++		themes = new ArrayList<Behavior>();
++
++		themes.add(new WindowsTheme());
++		themes.add(new HumanTheme());
++
++		theme = themes.get(0);
++
++		return themes;
++	}
++
++	@Override
++	public void detachModels()
++	{
++		for (Content content : contents)
++		{
++			content.detach();
++		}
++
++		super.detachModels();
++	}
++
++	protected Component newContentComponent(String id, IModel<Foo> model)
++	{
++		return content.newContentComponent(id, tree, model);
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.properties
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.properties
index 0000000,0000000..14ed1a4
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.properties
@@@ -1,0 -1,0 +1,15 @@@
++#  Licensed to the Apache Software Foundation (ASF) under one or more
++#  contributor license agreements.  See the NOTICE file distributed with
++#  this work for additional information regarding copyright ownership.
++#  The ASF licenses this file to You 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.
++form.theme.nullValid = - no theme -

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/BookmarkableFolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/BookmarkableFolderContent.java
index 0000000,0000000..816dfdf
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/BookmarkableFolderContent.java
@@@ -1,0 -1,0 +1,77 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.MarkupContainer;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.examples.tree.TreeApplication;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder;
++import org.apache.wicket.markup.html.link.BookmarkablePageLink;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.request.mapper.parameter.PageParameters;
++
++/**
++ * @author Sven Meier
++ */
++public class BookmarkableFolderContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	public BookmarkableFolderContent(final AbstractTree<Foo> tree)
++	{
++		String id = tree.getRequest().getRequestParameters().getParameterValue("foo").toString();
++		if (id != null)
++		{
++			Foo foo = TreeApplication.get().getFoo(id);
++			while (foo != null)
++			{
++				tree.getModel().getObject().add(foo);
++				foo = foo.getParent();
++			}
++		}
++	}
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new Folder<Foo>(id, tree, model)
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected MarkupContainer newLinkComponent(String id, IModel<Foo> model)
++			{
++				Foo foo = model.getObject();
++
++				if (tree.getProvider().hasChildren(foo))
++				{
++					return super.newLinkComponent(id, model);
++				}
++				else
++				{
++					PageParameters parameters = new PageParameters();
++					parameters.add("foo", foo.getId());
++
++					return new BookmarkablePageLink<Void>(id, tree.getPage().getClass(), parameters);
++				}
++			}
++		};
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedFolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedFolderContent.java
index 0000000,0000000..b988b6c
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedFolderContent.java
@@@ -1,0 -1,0 +1,96 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.CheckedFolder;
++import org.apache.wicket.extensions.markup.html.repeater.tree.util.ProviderSubset;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class CheckedFolderContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private ProviderSubset<Foo> checked;
++
++	public CheckedFolderContent(ITreeProvider<Foo> provider)
++	{
++		checked = new ProviderSubset<Foo>(provider, false);
++	}
++
++	@Override
++	public void detach()
++	{
++		checked.detach();
++	}
++
++	protected boolean isChecked(Foo foo)
++	{
++		return checked.contains(foo);
++	}
++
++	protected void check(Foo foo, boolean check)
++	{
++		if (check)
++		{
++			checked.add(foo);
++		}
++		else
++		{
++			checked.remove(foo);
++		}
++	}
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new CheckedFolder<Foo>(id, tree, model)
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected IModel<Boolean> newCheckBoxModel(final IModel<Foo> model)
++			{
++				return new IModel<Boolean>()
++				{
++					private static final long serialVersionUID = 1L;
++
++					public Boolean getObject()
++					{
++						return isChecked(model.getObject());
++					}
++
++					public void setObject(Boolean object)
++					{
++						check(model.getObject(), object);
++					}
++
++					public void detach()
++					{
++					}
++				};
++			}
++		};
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedSelectableFolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedSelectableFolderContent.java
index 0000000,0000000..820fcff
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedSelectableFolderContent.java
@@@ -1,0 -1,0 +1,90 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.CheckedFolder;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.model.PropertyModel;
++
++/**
++ * @author Sven Meier
++ */
++public class CheckedSelectableFolderContent extends SelectableFolderContent
++{
++
++	private static final long serialVersionUID = 1L;
++
++	public CheckedSelectableFolderContent(ITreeProvider<Foo> provider)
++	{
++		super(provider);
++	}
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new CheckedFolder<Foo>(id, tree, model)
++		{
++			private static final long serialVersionUID = 1L;
++
++			@Override
++			protected IModel<Boolean> newCheckBoxModel(final IModel<Foo> model)
++			{
++				return new PropertyModel<Boolean>(model, "quux");
++			}
++
++			@Override
++			protected void onUpdate(AjaxRequestTarget target)
++			{
++				Foo foo = getModelObject();
++
++				// search first ancestor with quux not set
++				while (!foo.getQuux() && foo.getParent() != null)
++				{
++					foo = foo.getParent();
++				}
++
++				tree.updateBranch(foo, target);
++			}
++
++			/**
++			 * Always clickable.
++			 */
++			@Override
++			protected boolean isClickable()
++			{
++				return true;
++			}
++
++			@Override
++			protected void onClick(AjaxRequestTarget target)
++			{
++				CheckedSelectableFolderContent.this.select(getModelObject(), tree, target);
++			}
++
++			@Override
++			protected boolean isSelected()
++			{
++				return CheckedSelectableFolderContent.this.isSelected(getModelObject());
++			}
++		};
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/Content.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/Content.java
index 0000000,0000000..f326cb2
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/Content.java
@@@ -1,0 -1,0 +1,45 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.model.IDetachable;
++import org.apache.wicket.model.IModel;
++
++/**
++ * Tree content factory for the {@link ContentPage}.
++ * 
++ * Note: This indirection is used for demonstration purposes only! Don't jump through similar hoops
++ * if you're just using one type of content for your application's trees.
++ * 
++ * @author Sven Meier
++ */
++public abstract class Content implements IDetachable
++{
++
++	/**
++	 * Create new content.
++	 */
++	public abstract Component newContentComponent(String id, AbstractTree<Foo> tree,
++		IModel<Foo> model);
++
++	public void detach()
++	{
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/EditableFolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/EditableFolderContent.java
index 0000000,0000000..e202bae
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/EditableFolderContent.java
@@@ -1,0 -1,0 +1,91 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.MarkupContainer;
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.ajax.markup.html.AjaxEditableLabel;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder;
++import org.apache.wicket.markup.ComponentTag;
++import org.apache.wicket.markup.html.WebMarkupContainer;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.model.PropertyModel;
++
++/**
++ * @author Sven Meier
++ */
++public class EditableFolderContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new Folder<Foo>(id, tree, model)
++		{
++
++			/**
++			 * Always clickable.
++			 */
++			@Override
++			protected boolean isClickable()
++			{
++				return true;
++			}
++
++			/**
++			 * AjaxEditableLabel won't work reliable in Safari if wrapped in a Link, so simply
++			 * replace the anchor with a &lt;span&gt;.
++			 */
++			@Override
++			protected MarkupContainer newLinkComponent(String id, IModel<Foo> model)
++			{
++				return new WebMarkupContainer(id)
++				{
++					@Override
++					protected void onComponentTag(ComponentTag tag)
++					{
++						tag.setName("span");
++						super.onComponentTag(tag);
++					}
++				};
++			}
++
++			@Override
++			protected Component newLabelComponent(String id, final IModel<Foo> model)
++			{
++				return new AjaxEditableLabel<String>(id, new PropertyModel<String>(model, "bar"))
++				{
++					@Override
++					protected void onSubmit(AjaxRequestTarget target)
++					{
++						super.onSubmit(target);
++
++						/**
++						 * update whole node in case we're located inside TableTree
++						 */
++						tree.updateNode(model.getObject(), target);
++					}
++				};
++			}
++		};
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/FolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/FolderContent.java
index 0000000,0000000..2fdc867
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/FolderContent.java
@@@ -1,0 -1,0 +1,38 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class FolderContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new Folder<Foo>(id, tree, model);
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/LabelContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/LabelContent.java
index 0000000,0000000..c703c6b
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/LabelContent.java
@@@ -1,0 -1,0 +1,38 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.markup.html.basic.Label;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class LabelContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new Label(id, model);
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MixedContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MixedContent.java
index 0000000,0000000..f9a35e7
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MixedContent.java
@@@ -1,0 -1,0 +1,49 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import java.util.ArrayList;
++import java.util.List;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class MixedContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private List<Content> contents;
++
++	public MixedContent(List<Content> contents)
++	{
++		this.contents = new ArrayList<Content>(contents);
++	}
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		int index = (int)(Math.random() * contents.size()) % contents.size();
++
++		return contents.get(index).newContentComponent(id, tree, model);
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiLineLabelContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiLineLabelContent.java
index 0000000,0000000..d8eec49
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiLineLabelContent.java
@@@ -1,0 -1,0 +1,49 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.markup.html.basic.MultiLineLabel;
++import org.apache.wicket.model.AbstractReadOnlyModel;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class MultiLineLabelContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private static final String LOREM_IPSUM = " - Lorem ipsum dolor sit amet,\nconsectetur, sadipisci velit...";
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree,
++		final IModel<Foo> model)
++	{
++		return new MultiLineLabel(id, new AbstractReadOnlyModel<String>()
++		{
++			@Override
++			public String getObject()
++			{
++				return model.getObject().getId() + " " + LOREM_IPSUM;
++			}
++		});
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiSelectableFolderContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiSelectableFolderContent.java
index 0000000,0000000..1579002
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiSelectableFolderContent.java
@@@ -1,0 -1,0 +1,97 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder;
++import org.apache.wicket.extensions.markup.html.repeater.tree.util.ProviderSubset;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class MultiSelectableFolderContent extends Content
++{
++
++	private static final long serialVersionUID = 1L;
++
++	private ProviderSubset<Foo> selected;
++
++	public MultiSelectableFolderContent(ITreeProvider<Foo> provider)
++	{
++		selected = new ProviderSubset<Foo>(provider, false);
++	}
++
++	@Override
++	public void detach()
++	{
++		selected.detach();
++	}
++
++	protected boolean isSelected(Foo foo)
++	{
++		return selected.contains(foo);
++	}
++
++	protected void toggle(Foo foo, AbstractTree<Foo> tree, final AjaxRequestTarget target)
++	{
++		if (isSelected(foo))
++		{
++			selected.remove(foo);
++		}
++		else
++		{
++			selected.add(foo);
++		}
++
++		tree.updateNode(foo, target);
++	}
++
++	@Override
++	public Component newContentComponent(String id, final AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new Folder<Foo>(id, tree, model)
++		{
++			private static final long serialVersionUID = 1L;
++
++			/**
++			 * Always clickable.
++			 */
++			@Override
++			protected boolean isClickable()
++			{
++				return true;
++			}
++
++			@Override
++			protected void onClick(AjaxRequestTarget target)
++			{
++				MultiSelectableFolderContent.this.toggle(getModelObject(), tree, target);
++			}
++
++			@Override
++			protected boolean isSelected()
++			{
++				return MultiSelectableFolderContent.this.isSelected(getModelObject());
++			}
++		};
++	}
++}

http://git-wip-us.apache.org/repos/asf/wicket/blob/05840d1c/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/PanelContent.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/PanelContent.java
index 0000000,0000000..1f4762e
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/PanelContent.java
@@@ -1,0 -1,0 +1,38 @@@
++/*
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You 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 org.apache.wicket.examples.tree.content;
++
++import org.apache.wicket.Component;
++import org.apache.wicket.examples.tree.Foo;
++import org.apache.wicket.examples.tree.FooPanel;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.model.IDetachable;
++import org.apache.wicket.model.IModel;
++
++/**
++ * @author Sven Meier
++ */
++public class PanelContent extends Content implements IDetachable
++{
++	private static final long serialVersionUID = 1L;
++
++	@Override
++	public Component newContentComponent(String id, AbstractTree<Foo> tree, IModel<Foo> model)
++	{
++		return new FooPanel(id, model);
++	}
++}