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
[1/9] git commit: Merge remote-tracking branch 'origin/master'
Updated Branches:
refs/heads/master 41ddc9ce7 -> 31726809e
Merge remote-tracking branch 'origin/master'
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/31726809
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/31726809
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/31726809
Branch: refs/heads/master
Commit: 31726809ec0401de0effd92060b99d6db3c83c21
Parents: 05840d1 41ddc9c
Author: Sven Meier <sv...@apache.org>
Authored: Sun Feb 5 21:31:14 2012 +0100
Committer: Sven Meier <sv...@apache.org>
Committed: Sun Feb 5 22:48:06 2012 +0100
----------------------------------------------------------------------
release-igor.sh | 25 +-
.../main/java/org/apache/wicket/Application.java | 5 +-
.../src/main/java/org/apache/wicket/Behaviors.java | 3 +-
.../src/main/java/org/apache/wicket/Component.java | 289 ++--
.../java/org/apache/wicket/MarkupContainer.java | 80 +-
.../src/main/java/org/apache/wicket/Page.java | 21 +-
.../src/main/java/org/apache/wicket/Session.java | 34 +-
.../apache/wicket/ajax/AbstractAjaxResponse.java | 748 +++++++
.../wicket/ajax/AbstractAjaxTimerBehavior.java | 22 +-
.../wicket/ajax/AbstractDefaultAjaxBehavior.java | 186 ++-
.../org/apache/wicket/ajax/AjaxEventBehavior.java | 33 +-
.../org/apache/wicket/ajax/AjaxRequestHandler.java | 491 +++++
.../org/apache/wicket/ajax/AjaxRequestTarget.java | 1258 +----------
.../ajax/AjaxRequestTargetListenerCollection.java | 2 +-
.../wicket/ajax/AjaxSelfUpdatingTimerBehavior.java | 2 +-
.../org/apache/wicket/ajax/XmlAjaxResponse.java | 230 ++
.../AjaxFormChoiceComponentUpdatingBehavior.java | 35 +-
.../form/AjaxFormComponentUpdatingBehavior.java | 24 +-
.../wicket/ajax/form/OnChangeAjaxBehavior.java | 2 +-
.../wicket/ajax/markup/html/AjaxFallbackLink.java | 4 -
.../wicket/ajax/markup/html/form/AjaxButton.java | 8 -
.../wicket/ajax/markup/html/form/AjaxCheckBox.java | 3 +-
.../ajax/markup/html/form/AjaxFallbackButton.java | 2 +-
.../wicket/ajax/res/js/wicket-ajax-jquery.js | 167 +-
.../wicket/ajax/res/js/wicket-event-jquery.js | 4 +-
.../strategy/DefaultAuthenticationStrategy.java | 9 +-
.../wicket/behavior/AbstractAjaxBehavior.java | 8 +-
.../behavior/InvalidBehaviorIdException.java | 12 +-
.../DefaultCleanupFeedbackMessageFilter.java | 35 +
.../feedback/ErrorLevelFeedbackMessageFilter.java | 1 +
.../apache/wicket/feedback/FeedbackCollector.java | 135 ++
.../apache/wicket/feedback/FeedbackMessages.java | 112 +-
.../wicket/feedback/FeedbackMessagesModel.java | 14 +-
.../wicket/feedback/IFeedbackMessageFilter.java | 14 +
.../org/apache/wicket/markup/MarkupParser.java | 4 +-
.../wicket/markup/head/CssContentHeaderItem.java | 16 +-
.../apache/wicket/markup/head/CssHeaderItem.java | 62 +-
.../wicket/markup/head/CssReferenceHeaderItem.java | 13 +-
.../markup/head/CssUrlReferenceHeaderItem.java | 11 +-
.../markup/head/JavaScriptContentHeaderItem.java | 17 +-
.../wicket/markup/head/JavaScriptHeaderItem.java | 124 +-
.../markup/head/JavaScriptReferenceHeaderItem.java | 5 +-
.../head/JavaScriptUrlReferenceHeaderItem.java | 7 +-
.../wicket/markup/head/ResourceAggregator.java | 8 +-
.../head/filter/AbstractHeaderResponseFilter.java | 56 +
.../filter/CssAcceptingHeaderResponseFilter.java | 46 +
.../CssAndPageAcceptingHeaderResponseFilter.java | 47 +
.../markup/head/filter/FilteredHeaderItem.java | 120 +
.../head/filter/FilteringHeaderResponse.java | 239 ++
.../head/filter/HeaderResponseContainer.java | 73 +
.../JavaScriptAcceptingHeaderResponseFilter.java | 50 +
...JavaScriptFilteredIntoFooterHeaderResponse.java | 72 +
.../head/filter/OppositeHeaderResponseFilter.java | 60 +
.../apache/wicket/markup/html/border/Border.java | 12 +-
.../org/apache/wicket/markup/html/form/Check.java | 10 +-
.../org/apache/wicket/markup/html/form/Form.java | 6 +-
.../wicket/markup/html/form/FormComponent.java | 12 +-
.../wicket/markup/html/form/StatelessForm.java | 32 +
.../validation/FormComponentFeedbackBorder.java | 4 +-
.../validation/FormComponentFeedbackIndicator.java | 5 +-
.../org/apache/wicket/markup/html/image/Image.java | 4 +-
.../wicket/markup/html/image/NonCachingImage.java | 2 +-
.../html/image/resource/BlobImageResource.java | 8 +-
.../wicket/markup/html/internal/Enclosure.java | 1 -
.../wicket/markup/parser/AbstractMarkupFilter.java | 32 +
.../parser/filter/RelativePathPrefixHandler.java | 24 +-
.../parser/filter/WicketMessageTagHandler.java | 37 +-
.../parser/filter/WicketNamespaceHandler.java | 7 +-
.../markup/parser/filter/WicketTagIdentifier.java | 7 +-
.../markup/resolver/WicketMessageResolver.java | 1 -
.../main/java/org/apache/wicket/model/Model.java | 32 +-
.../wicket/page/DefaultPageManagerContext.java | 2 +-
.../protocol/http/AjaxEnclosureListener.java | 4 +-
.../wicket/protocol/http/WebApplication.java | 37 +-
.../apache/wicket/protocol/http/WebSession.java | 62 -
.../apache/wicket/protocol/http/WicketFilter.java | 37 +-
.../protocol/http/mock/MockHttpServletRequest.java | 22 +-
.../protocol/http/servlet/ServletWebResponse.java | 23 +-
.../apache/wicket/request/cycle/RequestCycle.java | 98 +-
.../resource/ResourceReferenceRequestHandler.java | 4 +-
.../handler/resource/ResourceRequestHandler.java | 7 +-
.../request/mapper/AbstractBookmarkableMapper.java | 5 +
.../request/mapper/BufferedResponseMapper.java | 20 +-
.../apache/wicket/request/mapper/CryptoMapper.java | 2 +-
.../wicket/request/mapper/MountedMapper.java | 12 +-
.../wicket/request/resource/AbstractResource.java | 17 +-
.../wicket/request/resource/ClassScanner.java | 2 +-
.../wicket/request/resource/PackageResource.java | 38 +-
.../wicket/request/resource/ResourceReference.java | 2 +-
.../resource/ResourceReferenceRegistry.java | 16 +-
.../request/resource/ResourceStreamResource.java | 9 +-
.../version/MessageDigestResourceVersion.java | 2 +-
.../filtering/AbstractHeaderResponseFilter.java | 56 -
.../CssAcceptingHeaderResponseFilter.java | 53 -
...erResponseContainerFilteringHeaderResponse.java | 228 --
.../HeaderResponseFilteredResponseContainer.java | 73 -
.../JavaScriptAcceptingHeaderResponseFilter.java | 38 -
...JavaScriptFilteredIntoFooterHeaderResponse.java | 67 -
.../filtering/OppositeHeaderResponseFilter.java | 60 -
.../apache/wicket/session/DefaultPageFactory.java | 8 +-
.../wicket/settings/IApplicationSettings.java | 18 +
.../org/apache/wicket/settings/IPageSettings.java | 18 +
.../wicket/settings/def/ApplicationSettings.java | 18 +
.../apache/wicket/settings/def/PageSettings.java | 13 +
.../util/io/WicketSerializeableException.java | 92 -
.../wicket/util/resource/UrlResourceStream.java | 7 +-
.../wicket/util/tester/BaseWicketTester.java | 89 +-
.../org/apache/wicket/util/tester/FormTester.java | 2 +-
.../apache/wicket/util/tester/WicketTester.java | 7 +-
...ponentBehaviorOverComponentTagBehaviorTest.java | 83 +
.../org/apache/wicket/FeedbackMessagesTest.java | 6 +-
.../java/org/apache/wicket/MockPanelWithLink.java | 2 +-
...ResponseAtInterceptPageExceptionInAjaxTest.java | 7 -
.../apache/wicket/ajax/AjaxRequestHandlerTest.java | 361 +++
.../apache/wicket/ajax/AjaxRequestTargetTest.java | 361 ---
.../OnChangeAjaxBehaviorTestPage_expected.html | 4 +-
.../SimpleTestPageExpectedResult-1.html | 2 +-
.../componentMap/SimpleTestPageExpectedResult.html | 2 +-
.../wicket/markup/html/HeaderContributorTest.java | 4 +-
.../markup/html/TransparentWithAjaxUpdatePage.java | 2 +-
.../html/form/LocalizedErrorMessageTest.java | 4 +-
.../markup/html/form/ValidatorPropertiesTest.java | 112 +-
.../form/feedback/FeedbackFormPage_result2.html | 2 +-
.../form/validation/FormValidatorBehaviorTest.java | 27 +-
.../innerfeedback/LocalizedFeedbackBorder.java | 13 +-
.../markup/html/internal/HeaderResponseTest.java | 314 ++-
.../internal/TraditionalEnclosureAjaxPage.java | 1 -
.../markup/html/link/HrefExpectedResult_2.html | 4 +-
.../markup/html/link/MountedPageLinkTest.java | 108 +
.../wicket/markup/html/link/PageWithLink.html | 8 +
.../wicket/markup/html/link/PageWithLink.java | 40 +
.../wicket/markup/html/panel/FragmentTestCase.java | 2 +-
.../apache/wicket/markup/html/panel/PanelTest.java | 2 +-
.../AbstractTransformerBehaviorTest.java | 4 +-
.../http/mock/MockHttpServletRequestTest.java | 36 +
.../http/servlet/ServletWebResponseTest.java | 43 -
.../request/cycle/RequestCycleUrlForTest.java | 200 ++
.../wicket/request/handler/PageIdPoliticTest.java | 1 -
.../wicket/request/mapper/CryptoMapperTest.java | 18 +
.../wicket/request/mapper/MountedMapperTest.java | 18 +
.../apache/wicket/request/mapper/UrlInfoTest.java | 2 +-
.../wicket/response/filter/ResponseFilterTest.java | 1 -
.../wicket/stateless/StatelessFormUrlTest.java | 35 +-
.../wicket/util/tester/WicketTesterTest.java | 48 +-
.../wicket/util/tester/apps_4/FormTesterTest.java | 14 +-
.../wicket/validation/ValidatorBehaviorTest.java | 27 +-
wicket-core/src/test/js/ajax.js | 67 +-
wicket-core/src/test/js/event.js | 22 +
wicket-core/src/test/js/head.js | 3 +-
.../wicket/extensions/yui/calendar/DatePicker.java | 15 +-
.../wicket/extensions/yui/calendar/calendar-min.js | 28 +-
.../apache/wicket/devutils/debugbar/DebugBar.java | 1 -
.../src/disabled/java/ng/NGApplication.java | 48 -
.../src/disabled/java/ng/TestPage1.java | 146 --
.../src/disabled/java/ng/TestPage2.java | 28 -
.../src/disabled/java/ng/TestPage3.java | 45 -
.../src/disabled/java/ng/TestPage4.java | 42 -
.../wicket/examples/ajax/builtin/EffectsPage.java | 2 +-
.../wicket/examples/ajax/builtin/GuestBook.java | 8 +-
.../wicket/examples/ajax/builtin/LinksPage.java | 4 +-
.../wicket/examples/ajax/builtin/TodoList.java | 2 +-
.../wicket/examples/compref/RadioChoicePage.java | 17 +-
.../wicket/examples/library/LibrarySession.java | 4 +-
.../examples/resourcedecoration/HomePage.html | 3 +-
.../examples/resourcedecoration/HomePage.java | 18 +-
.../ResourceDecorationApplication.java | 2 +-
.../wicket/examples/resourcedecoration/app.css | 5 +-
.../wicket/examples/resourcedecoration/top.js | 20 +
.../apache/wicket/examples/source/SourcesPage.java | 34 +-
.../wicket/examples/stateless/StatelessPage3.java | 3 -
.../apache/wicket/examples/tree/InverseSet.java | 143 ++
.../org/apache/wicket/examples/tree/TreePage.java | 3 +-
.../tree/content/CheckedFolderContent.java | 2 +-
.../tree/content/MultiSelectableFolderContent.java | 2 +-
.../org/apache/wicket/examples/StartExamples.java | 2 +
.../wicket/examples/tree/InverseSetTest.java | 77 +
.../ajax/markup/html/AjaxEditableLabel.java | 77 +-
.../ajax/markup/html/AjaxIndicatorAppender.java | 2 +-
.../ajax/markup/html/AjaxLazyLoadPanel.java | 4 +-
.../autocomplete/AbstractAutoCompleteBehavior.java | 2 +-
.../html/autocomplete/wicket-autocomplete.js | 2 -
.../ajax/markup/html/modal/ModalWindow.java | 16 +-
.../extensions/ajax/markup/html/modal/res/modal.js | 2 +-
.../data/sort/AjaxFallbackOrderByLink.java | 2 +-
.../repeater/data/table/AjaxNavigationToolbar.java | 2 +-
.../breadcrumb/panel/BreadCrumbPanelFactory.java | 6 +-
.../breadcrumb/panel/BreadCrumbPanelLink.java | 13 +-
.../captcha/kittens/KittenCaptchaPanel.java | 29 +-
.../extensions/markup/html/form/select/Select.java | 9 +-
.../image/resource/ThumbnailImageResource.java | 2 +-
.../markup/html/repeater/tree/AbstractTree.java | 6 +-
.../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 ---
.../markup/html/repeater/util/ProviderSubset.java | 242 ++
.../html/repeater/util/SortableTreeProvider.java | 95 +
.../html/repeater/util/TreeModelProvider.java | 258 +++
.../extensions/markup/html/tree/AbstractTree.java | 8 +-
.../extensions/markup/html/tree/BaseTree.java | 2 +-
.../markup/html/tree/DefaultAbstractTree.java | 2 +-
.../wicket/extensions/rating/RatingPanel.java | 2 +-
.../html/repeater/tree/util/InverseSetTest.java | 77 -
.../repeater/tree/util/ProviderSubsetTest.java | 170 --
.../repeater/tree/util/TreeModelProviderTest.java | 155 --
.../html/repeater/util/ProviderSubsetTest.java | 171 ++
.../html/repeater/util/TreeModelProviderTest.java | 156 ++
.../wicket/guice/GuiceComponentInjector.java | 10 +-
.../apache/wicket/proxy/LazyInitProxyFactory.java | 4 +-
.../apache/wicket/proxy/util/InterfaceObject.java | 1 -
.../apache/wicket/request/http/WebResponse.java | 7 +-
.../request/mapper/parameter/PageParameters.java | 18 +
.../mapper/parameter/PageParametersEncoder.java | 15 +-
.../parameter/UrlPathPageParametersEncoder.java | 3 +
.../CombinedRequestParametersAdapter.java | 10 +-
.../parameter/UrlRequestParametersAdapter.java | 4 +-
.../parameter/PageParametersEncoderTest.java | 126 ++
.../apache/wicket/spring/SpringWebApplication.java | 3 +-
.../annot/AnnotProxyFieldValueFactory.java | 9 +-
.../injection/annot/SpringComponentInjector.java | 10 +-
.../org/apache/wicket/util/io/Connections.java | 10 +
.../apache/wicket/util/io/FullyBufferedReader.java | 13 -
.../wicket/util/resource/IResourceStream.java | 3 +-
.../org/apache/wicket/util/string/StringValue.java | 1678 ++++++++-------
.../wicket/util/value/CopyOnWriteValueMap.java | 905 ++++----
.../org/apache/wicket/util/value/ValueMap.java | 1708 +++++++--------
.../apache/wicket/util/string/StringValueTest.java | 52 +
228 files changed, 8934 insertions(+), 7337 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/wicket-examples/src/main/java/org/apache/wicket/examples/tree/InverseSet.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/main/java/org/apache/wicket/examples/tree/InverseSet.java
index 0000000,0000000..74f0258
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/InverseSet.java
@@@ -1,0 -1,0 +1,143 @@@
++/*
++ * 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.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++import org.apache.wicket.model.IDetachable;
++
++/**
++ * An inverse set.
++ *
++ * @author svenmeier
++ */
++public class InverseSet<T> implements Set<T>, IDetachable
++{
++
++ private static final long serialVersionUID = 1L;
++
++ private Set<T> set;
++
++ /**
++ * Create a full set.
++ *
++ * @param set
++ * the contained set
++ */
++ public InverseSet(Set<T> set)
++ {
++ this.set = set;
++ }
++
++ public void detach()
++ {
++ if (set instanceof IDetachable)
++ {
++ ((IDetachable)set).detach();
++ }
++ }
++
++ public boolean isEmpty()
++ {
++ return !set.isEmpty();
++ }
++
++ public boolean contains(Object o)
++ {
++ return !set.contains(o);
++ }
++
++ public boolean add(T t)
++ {
++ return set.remove(t);
++ }
++
++ @SuppressWarnings("unchecked")
++ public boolean remove(Object o)
++ {
++ return set.add((T)o);
++ }
++
++ public boolean addAll(Collection<? extends T> ts)
++ {
++ boolean changed = false;
++
++ for (T t : ts)
++ {
++ changed |= set.remove(t);
++ }
++
++ return changed;
++ }
++
++ public boolean containsAll(Collection<?> cs)
++ {
++ for (Object c : cs)
++ {
++ if (set.contains(c))
++ {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ @SuppressWarnings("unchecked")
++ public boolean removeAll(Collection<?> cs)
++ {
++ boolean changed = false;
++
++ for (Object c : cs)
++ {
++ changed |= set.add((T)c);
++ }
++
++ return changed;
++ }
++
++ public int size()
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear()
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public Iterator<T> iterator()
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> c)
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public Object[] toArray()
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public <S> S[] toArray(S[] a)
++ {
++ throw new UnsupportedOperationException();
++ }
++}
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/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 eb5b9f8,0000000..da6a7bf
mode 100644,000000..100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/TreePage.java
@@@ -1,236 -1,0 +1,235 @@@
+/*
+ * 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.extensions.markup.html.repeater.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/31726809/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 b988b6c,0000000..2c393fe
mode 100644,000000..100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedFolderContent.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/CheckedFolderContent.java
@@@ -1,96 -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.extensions.markup.html.repeater.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/31726809/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 1579002,0000000..af99373
mode 100644,000000..100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiSelectableFolderContent.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/tree/content/MultiSelectableFolderContent.java
@@@ -1,97 -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.extensions.markup.html.repeater.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/31726809/wicket-examples/src/test/java/org/apache/wicket/examples/tree/InverseSetTest.java
----------------------------------------------------------------------
diff --cc wicket-examples/src/test/java/org/apache/wicket/examples/tree/InverseSetTest.java
index 0000000,0000000..c0788a6
new file mode 100644
--- /dev/null
+++ b/wicket-examples/src/test/java/org/apache/wicket/examples/tree/InverseSetTest.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;
++
++import java.util.HashSet;
++
++import junit.framework.Assert;
++
++import org.apache.wicket.model.IDetachable;
++import org.junit.Test;
++
++/**
++ * Test for {@link InverseSet}.
++ *
++ * @author svenmeier
++ */
++public class InverseSetTest extends Assert
++{
++ private TestSet set;
++
++ /**
++ * Construct.
++ */
++ public InverseSetTest()
++ {
++ set = new TestSet();
++ set.add("A");
++ }
++
++ /**
++ * Test contains.
++ */
++ @Test
++ public void contains()
++ {
++ InverseSet<String> inverse = new InverseSet<String>(set);
++ assertFalse(inverse.contains("A"));
++ assertTrue(inverse.contains("B"));
++
++ inverse.remove("B");
++ assertFalse(inverse.contains("A"));
++ assertFalse(inverse.contains("B"));
++
++ inverse.add("A");
++ assertTrue(inverse.contains("A"));
++ assertFalse(inverse.contains("B"));
++
++ inverse.detach();
++ assertTrue(set.detached);
++ }
++
++ private class TestSet extends HashSet<String> implements IDetachable
++ {
++ private static final long serialVersionUID = 1L;
++
++ boolean detached = false;
++
++ public void detach()
++ {
++ detached = true;
++ }
++ }
++}
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/tree/AbstractTree.java
----------------------------------------------------------------------
diff --cc wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/tree/AbstractTree.java
index 2dd8425,0000000..464fa35
mode 100644,000000..100644
--- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/tree/AbstractTree.java
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/tree/AbstractTree.java
@@@ -1,343 -1,0 +1,343 @@@
+/*
+ * 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.extensions.markup.html.repeater.tree;
+
+import java.util.Set;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
- import org.apache.wicket.extensions.markup.html.repeater.tree.util.ProviderSubset;
++import org.apache.wicket.extensions.markup.html.repeater.util.ProviderSubset;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.repeater.DefaultItemReuseStrategy;
+import org.apache.wicket.markup.repeater.IItemReuseStrategy;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
+
+/**
+ * Abstract base class for {@link NestedTree} and {@link TableTree}. Uses its model for storing the
+ * {@link State} of its nodes.
+ *
+ * Note that a tree has no notion of a <em>selection</em>. Handling state of nodes besides
+ * expanse/collapse is irrelevant to a tree implementation.
+ *
+ * @see #newContentComponent(String, IModel)
+ *
+ * @author svenmeier
+ * @param <T>
+ * the model object type
+ */
+public abstract class AbstractTree<T> extends Panel
+{
+ private static final long serialVersionUID = 1L;
+
+ private ITreeProvider<T> provider;
+
+ private IItemReuseStrategy itemReuseStrategy;
+
+ protected AbstractTree(String id, ITreeProvider<T> provider)
+ {
+ this(id, provider, null);
+ }
+
+ protected AbstractTree(String id, ITreeProvider<T> provider, IModel<Set<T>> state)
+ {
+ super(id, state);
+
+ if (provider == null)
+ {
+ throw new IllegalArgumentException("argument [provider] cannot be null");
+ }
+ this.provider = provider;
+
+ // see #updateBranch(Object, AjaxRequestTarget)
+ setOutputMarkupId(true);
+ }
+
+ /**
+ * Sets the item reuse strategy. This strategy controls the creation of {@link Item}s.
+ *
+ * @see IItemReuseStrategy
+ *
+ * @param strategy
+ * item reuse strategy
+ * @return this for chaining
+ */
+ public AbstractTree<T> setItemReuseStrategy(IItemReuseStrategy strategy)
+ {
+ this.itemReuseStrategy = strategy;
+
+ return this;
+ }
+
+ /**
+ * @return currently set item reuse strategy. Defaults to <code>DefaultItemReuseStrategy</code>
+ * if none was set.
+ *
+ * @see DefaultItemReuseStrategy
+ */
+ public IItemReuseStrategy getItemReuseStrategy()
+ {
+ if (itemReuseStrategy == null)
+ {
+ return DefaultItemReuseStrategy.getInstance();
+ }
+ return itemReuseStrategy;
+ }
+
+ /**
+ * Get the provider of the tree nodes.
+ *
+ * @return provider
+ */
+ public ITreeProvider<T> getProvider()
+ {
+ return provider;
+ }
+
+ /**
+ * Delegate to {@link #newModel()} if none is inited in super implementation.
+ */
+ @Override
+ protected IModel<?> initModel()
+ {
+ IModel<?> model = super.initModel();
+
+ if (model == null)
+ {
+ model = newModel();
+ }
+
+ return model;
+ }
+
+ /**
+ * Factory method for a model, by default creates a model containing a {@link ProviderSubset}.
+ *
+ * @return model for this tree
+ */
+ protected IModel<Set<T>> newModel()
+ {
+ return new ProviderSubset<T>(provider).createModel();
+ }
+
+ /**
+ * Get the model of this tree.
+ *
+ * @return model
+ */
+ @SuppressWarnings("unchecked")
+ public IModel<Set<T>> getModel()
+ {
+ return (IModel<Set<T>>)getDefaultModel();
+ }
+
+ /**
+ * Get the model object of this tree.
+ *
+ * @return the model object
+ */
+ public Set<T> getModelObject()
+ {
+ return getModel().getObject();
+ }
+
+ /**
+ * Set the model.
+ *
+ * @param model
+ * the model
+ */
+ public void setModel(IModel<Set<T>> model)
+ {
+ setDefaultModel(model);
+ }
+
+ /**
+ * Set the model object.
+ *
+ * @param state
+ * the model object
+ */
+ public void setModelObject(Set<T> state)
+ {
+ setDefaultModelObject(state);
+ }
+
+ /**
+ * Expand the given node, tries to update the affected branch if the change happens on an
+ * {@link AjaxRequestTarget}.
+ *
+ * @param t
+ * the node to expand
+ *
+ * @see #getModelObject()
+ * @see Set#add(Object)
+ * @see #updateBranch(Object, AjaxRequestTarget)
+ */
+ public void expand(T t)
+ {
+ getModelObject().add(t);
+
- updateBranch(t, AjaxRequestTarget.get());
++ updateBranch(t, getRequestCycle().find(AjaxRequestTarget.class));
+ }
+
+ /**
+ * Collapse the given node, tries to update the affected branch if the change happens on an
+ * {@link AjaxRequestTarget}.
+ *
+ * @param t
+ * the object to collapse
+ *
+ * @see #getModelObject()
+ * @see Set#remove(Object)
+ * @see #updateBranch(Object, AjaxRequestTarget)
+ */
+ public void collapse(T t)
+ {
+ getModelObject().remove(t);
+
- updateBranch(t, AjaxRequestTarget.get());
++ updateBranch(t, getRequestCycle().find(AjaxRequestTarget.class));
+ }
+
+ /**
+ * Get the given node's {@link State}.
+ *
+ * @param t
+ * the node to get state for
+ * @return state
+ *
+ * @see #getModelObject()
+ * @see Set#contains(Object)
+ */
+ public State getState(T t)
+ {
+ if (getModelObject().contains(t))
+ {
+ return State.EXPANDED;
+ }
+ else
+ {
+ return State.COLLAPSED;
+ }
+ }
+
+ /**
+ * Overriden to detach the {@link ITreeProvider}.
+ */
+ @Override
+ protected void onDetach()
+ {
+ provider.detach();
+
+ super.onDetach();
+ }
+
+ /**
+ * Create a new component for a node.
+ *
+ * @param id
+ * the component id
+ * @param model
+ * the model containing the node
+ * @return created component
+ */
+ public Component newNodeComponent(String id, final IModel<T> model)
+ {
+ return new Node<T>(id, this, model)
+ {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected Component createContent(String id, IModel<T> model)
+ {
+ return AbstractTree.this.newContentComponent(id, model);
+ }
+ };
+ }
+
+ /**
+ * Create a new component for the content of a node.
+ *
+ * @param id
+ * the component id
+ * @param model
+ * the model containing the node
+ * @return created component
+ */
+ protected abstract Component newContentComponent(String id, IModel<T> model);
+
+ /**
+ * Convenience method to update a single branch on an {@link AjaxRequestTarget}. Does nothing if
+ * the given node is currently not visible or target is <code>null</code>.
+ *
+ * This default implementation adds this whole component for rendering.
+ *
+ * @param t
+ * @param target
+ */
+ public void updateBranch(T t, final AjaxRequestTarget target)
+ {
+ if (target != null)
+ {
+ target.add(this);
+ }
+ }
+
+ /**
+ * Convenience method to update a single node on an {@link AjaxRequestTarget}. Does nothing if
+ * the given node is currently not visible or target is <code>null</code>.
+ *
+ * @param t
+ * @param target
+ */
+ public void updateNode(T t, final AjaxRequestTarget target)
+ {
+ if (target != null)
+ {
+ final IModel<T> model = getProvider().model(t);
+ visitChildren(Node.class, new IVisitor<Node<T>, Void>()
+ {
+ public void component(Node<T> node, IVisit<Void> visit)
+ {
+ if (model.equals(node.getModel()))
+ {
+ target.add(node);
+ visit.stop();
+ }
+ visit.dontGoDeeper();
+ }
+ });
+ model.detach();
+ }
+ }
+
+ /**
+ * The state of a node.
+ */
+ public static enum State {
+ /**
+ * The node is collapsed, i.e. its children are not iterated.
+ */
+ COLLAPSED,
+ /**
+ * The node is expanded, i.e. its children are iterated.
+ */
+ EXPANDED
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/ProviderSubset.java
----------------------------------------------------------------------
diff --cc wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/ProviderSubset.java
index 0000000,0000000..dd9d46e
new file mode 100644
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/ProviderSubset.java
@@@ -1,0 -1,0 +1,242 @@@
++/*
++ * 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.extensions.markup.html.repeater.util;
++
++import java.util.Collection;
++import java.util.HashSet;
++import java.util.Iterator;
++import java.util.Set;
++
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.model.AbstractReadOnlyModel;
++import org.apache.wicket.model.IDetachable;
++import org.apache.wicket.model.IModel;
++
++/**
++ * A subset of a {@link ITreeProvider}'s tree offering automatic detachment.
++ *
++ * Make sure that the containing model calls {@link IDetachable#detach()} on its model object.
++ *
++ * @see ITreeProvider#model(Object)
++ *
++ * @author svenmeier
++ */
++public class ProviderSubset<T> implements Set<T>, IDetachable
++{
++
++ private static final long serialVersionUID = 1L;
++
++ private ITreeProvider<T> provider;
++
++ private Set<IModel<T>> models = new HashSet<IModel<T>>();
++
++ /**
++ * Create an empty subset.
++ *
++ * @param provider
++ * the provider of the complete set
++ */
++ public ProviderSubset(ITreeProvider<T> provider)
++ {
++ this(provider, false);
++ }
++
++ /**
++ * Create a subset optionally containing all roots of the provider.
++ *
++ * @param provider
++ * the provider of the complete set
++ * @param addRoots
++ * should all roots be added to this subset
++ */
++ public ProviderSubset(ITreeProvider<T> provider, boolean addRoots)
++ {
++ this.provider = provider;
++
++ if (addRoots)
++ {
++ Iterator<? extends T> roots = provider.getRoots();
++ while (roots.hasNext())
++ {
++ add(roots.next());
++ }
++ }
++ }
++
++ public void detach()
++ {
++ for (IModel<T> model : models)
++ {
++ model.detach();
++ }
++ }
++
++ public int size()
++ {
++ return models.size();
++ }
++
++ public boolean isEmpty()
++ {
++ return models.size() == 0;
++ }
++
++ public void clear()
++ {
++ detach();
++
++ models.clear();
++ }
++
++ public boolean contains(Object o)
++ {
++ IModel<T> model = model(o);
++
++ boolean contains = models.contains(model);
++
++ model.detach();
++
++ return contains;
++ }
++
++ public boolean add(T t)
++ {
++ return models.add(model(t));
++ }
++
++ public boolean remove(Object o)
++ {
++ IModel<T> model = model(o);
++
++ boolean removed = models.remove(model);
++
++ model.detach();
++
++ return removed;
++ }
++
++ public Iterator<T> iterator()
++ {
++ return new Iterator<T>()
++ {
++
++ private Iterator<IModel<T>> iterator = models.iterator();
++
++ private IModel<T> current;
++
++ public boolean hasNext()
++ {
++ return iterator.hasNext();
++ }
++
++ public T next()
++ {
++ current = iterator.next();
++
++ return current.getObject();
++ }
++
++ public void remove()
++ {
++ iterator.remove();
++
++ current.detach();
++ current = null;
++ }
++ };
++ }
++
++ public boolean addAll(Collection<? extends T> ts)
++ {
++ boolean changed = false;
++
++ for (T t : ts)
++ {
++ changed |= add(t);
++ }
++
++ return changed;
++ }
++
++ public boolean containsAll(Collection<?> cs)
++ {
++ for (Object c : cs)
++ {
++ if (!contains(c))
++ {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ public boolean removeAll(Collection<?> cs)
++ {
++ boolean changed = false;
++
++ for (Object c : cs)
++ {
++ changed |= remove(c);
++ }
++
++ return changed;
++ }
++
++ public boolean retainAll(Collection<?> c)
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public Object[] toArray()
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ public <S> S[] toArray(S[] a)
++ {
++ throw new UnsupportedOperationException();
++ }
++
++ @SuppressWarnings("unchecked")
++ private IModel<T> model(Object o)
++ {
++ return provider.model((T)o);
++ }
++
++ /**
++ * Create a model holding this set.
++ *
++ * @return model
++ */
++ public IModel<Set<T>> createModel()
++ {
++ return new AbstractReadOnlyModel<Set<T>>()
++ {
++ @Override
++ public Set<T> getObject()
++ {
++ return ProviderSubset.this;
++ }
++
++ @Override
++ public void detach()
++ {
++ ProviderSubset.this.detach();
++ }
++ };
++ }
++}
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/SortableTreeProvider.java
----------------------------------------------------------------------
diff --cc wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/SortableTreeProvider.java
index 0000000,0000000..9260508
new file mode 100644
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/SortableTreeProvider.java
@@@ -1,0 -1,0 +1,95 @@@
++/*
++ * 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.extensions.markup.html.repeater.util;
++
++import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
++import org.apache.wicket.extensions.markup.html.repeater.tree.ISortableTreeProvider;
++
++/**
++ * Convenience implementation of a tree provider that can also act as a locator for a
++ * {@link SingleSortState} object.
++ *
++ * @author svenmeier
++ */
++public abstract class SortableTreeProvider<T> implements ISortableTreeProvider<T>
++{
++ private SingleSortState state = new SingleSortState();
++
++ /**
++ * @see ISortableDataProvider#getSortState()
++ */
++ public final ISortState getSortState()
++ {
++ return state;
++ }
++
++ /**
++ * @see ISortableDataProvider#setSortState(org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState)
++ */
++ public final void setSortState(ISortState state)
++ {
++ if (!(state instanceof SingleSortState))
++ {
++ throw new IllegalArgumentException(
++ "argument [state] must be an instance of SingleSortState, but it is [" +
++ state.getClass().getName() + "]:[" + state.toString() + "]");
++ }
++ this.state = (SingleSortState)state;
++ }
++
++ /**
++ * Returns current sort state
++ *
++ * @return current sort state
++ */
++ public SortParam getSort()
++ {
++ return state.getSort();
++ }
++
++ /**
++ * Sets the current sort state
++ *
++ * @param param
++ * parameter containing new sorting information
++ */
++ public void setSort(SortParam param)
++ {
++ state.setSort(param);
++ }
++
++ /**
++ * Sets the current sort state
++ *
++ * @param property
++ * sort property
++ * @param ascending
++ * sort direction
++ */
++ public void setSort(String property, boolean ascending)
++ {
++ setSort(new SortParam(property, ascending));
++ }
++
++ /**
++ * @see ISortableDataProvider#detach()
++ */
++ public void detach()
++ {
++ }
++}
http://git-wip-us.apache.org/repos/asf/wicket/blob/31726809/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/TreeModelProvider.java
----------------------------------------------------------------------
diff --cc wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/TreeModelProvider.java
index 0000000,0000000..9816d76
new file mode 100644
--- /dev/null
+++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/repeater/util/TreeModelProvider.java
@@@ -1,0 -1,0 +1,258 @@@
++/*
++ * 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.extensions.markup.html.repeater.util;
++
++import java.io.Serializable;
++import java.util.ArrayList;
++import java.util.Iterator;
++import java.util.List;
++
++import javax.swing.event.TreeModelEvent;
++import javax.swing.event.TreeModelListener;
++import javax.swing.tree.TreeModel;
++
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.extensions.markup.html.repeater.tree.AbstractTree;
++import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
++import org.apache.wicket.model.IModel;
++
++/**
++ * A provider wrapping a Swing {@link TreeModel}.
++ *
++ * EXPERIMENTAL !
++ *
++ * @author svenmeier
++ * @param <T>
++ * model object type
++ */
++public abstract class TreeModelProvider<T> implements ITreeProvider<T>
++{
++
++ private static final long serialVersionUID = 1L;
++
++ private final TreeModel treeModel;
++
++ private final boolean rootVisible;
++
++ protected boolean completeUpdate;
++
++ protected List<T> nodeUpdates;
++
++ protected List<T> branchUpdates;
++
++ /**
++ * Wrap the given {@link TreeModel}.
++ *
++ * @param treeModel
++ * model to wrap
++ */
++ public TreeModelProvider(TreeModel treeModel)
++ {
++ this(treeModel, true);
++ }
++
++ /**
++ * Wrap the given {@link TreeModel}.
++ *
++ * @param treeModel
++ * the wrapped model
++ * @param rootVisible
++ * should the root be visible
++ */
++ public TreeModelProvider(TreeModel treeModel, boolean rootVisible)
++ {
++ this.treeModel = treeModel;
++ this.rootVisible = rootVisible;
++
++ treeModel.addTreeModelListener(new Listener());
++ }
++
++ public Iterator<T> getRoots()
++ {
++ if (rootVisible)
++ {
++ return new Iterator<T>()
++ {
++ boolean next = true;
++
++ public boolean hasNext()
++ {
++ return next;
++ }
++
++ public T next()
++ {
++ next = false;
++ return cast(treeModel.getRoot());
++ }
++
++ public void remove()
++ {
++ throw new UnsupportedOperationException();
++ }
++ };
++ }
++ else
++ {
++ return getChildren(cast(treeModel.getRoot()));
++ }
++ }
++
++ public boolean hasChildren(T object)
++ {
++ return !treeModel.isLeaf(object);
++ }
++
++ public Iterator<T> getChildren(final T object)
++ {
++ return new Iterator<T>()
++ {
++ private int size = treeModel.getChildCount(object);
++ private int index = -1;
++
++ public boolean hasNext()
++ {
++ return index < size - 1;
++ }
++
++ public T next()
++ {
++ index++;
++ return cast(treeModel.getChild(object, index));
++ }
++
++ public void remove()
++ {
++ throw new UnsupportedOperationException();
++ }
++ };
++ }
++
++ @SuppressWarnings("unchecked")
++ protected T cast(Object object)
++ {
++ return (T)object;
++ }
++
++ public abstract IModel<T> model(T object);
++
++ public void detach()
++ {
++ completeUpdate = false;
++ nodeUpdates = null;
++ branchUpdates = null;
++ }
++
++ /**
++ * Call this method after all change to the wrapped {@link TreeModel} being initiated via
++ * {@link AjaxRequestTarget}.
++ *
++ * @param tree
++ * the tree utilizing this {@link ITreeProvider}
++ * @param target
++ * the {@link AjaxRequestTarget} which initiated the changes
++ */
++ public void update(AbstractTree<T> tree, AjaxRequestTarget target)
++ {
++ if (completeUpdate)
++ {
++ target.add(tree);
++ }
++ else
++ {
++ if (nodeUpdates != null)
++ {
++ for (T object : nodeUpdates)
++ {
++ tree.updateNode(object, target);
++ }
++ }
++
++ if (branchUpdates != null)
++ {
++ for (T object : branchUpdates)
++ {
++ tree.updateBranch(object, target);
++ }
++ }
++ }
++
++ detach();
++ }
++
++ protected void nodeUpdate(Object[] nodes)
++ {
++ if (nodeUpdates == null)
++ {
++ nodeUpdates = new ArrayList<T>();
++ }
++
++ for (Object node : nodes)
++ {
++ nodeUpdates.add(cast(node));
++ }
++ }
++
++ protected void branchUpdate(Object branch)
++ {
++ if (branchUpdates == null)
++ {
++ branchUpdates = new ArrayList<T>();
++ }
++
++ branchUpdates.add(cast(branch));
++ }
++
++ private class Listener implements TreeModelListener, Serializable
++ {
++ private static final long serialVersionUID = 1L;
++
++ public void treeNodesChanged(TreeModelEvent e)
++ {
++ if (e.getChildIndices() == null)
++ {
++ completeUpdate = true;
++ }
++ else
++ {
++ nodeUpdate(e.getChildren());
++ }
++ }
++
++ public void treeNodesInserted(TreeModelEvent e)
++ {
++ branchUpdate(e.getTreePath().getLastPathComponent());
++ }
++
++ public void treeNodesRemoved(TreeModelEvent e)
++ {
++ branchUpdate(e.getTreePath().getLastPathComponent());
++ }
++
++ public void treeStructureChanged(TreeModelEvent e)
++ {
++ if (e.getTreePath().getPathCount() == 1)
++ {
++ completeUpdate = true;
++ }
++ else
++ {
++ branchUpdate(e.getTreePath().getLastPathComponent());
++ }
++ }
++ }
++}