You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/04/17 07:26:07 UTC
[isis] 11/11: ISIS-898 initial (naive) lazy tree feature
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch dev/2.0.0/ISIS-898-treeview
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 0e3abd90395665e94d76bacf55e39b3286ec39c3
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Apr 17 09:24:52 2018 +0200
ISIS-898 initial (naive) lazy tree feature
fails when lazily fetching child nodes
---
.../org/apache/isis/applib/tree/LazyTreeNode.java | 7 +-
.../java/org/apache/isis/applib/tree/TreeNode.java | 51 ++---
.../facets/value/treenode/TreeNodeValueFacet.java} | 17 +-
...deValueFacetUsingSemanticsProviderFactory.java} | 30 +--
.../treenode/TreeNodeValueSemanticsProvider.java | 133 +++++++++++++
.../ComponentFactoryRegistrarDefault.java | 3 +-
.../wicket/model/models/tree/TreeViewModel.java | 1 +
.../components/tree/IsisToWicketTreeAdapter.java | 209 +++++++++++++++++++++
.../ui/components/tree/StandaloneTreePanel.html | 4 +-
.../ui/components/tree/StandaloneTreePanel.java | 14 +-
.../wicket/ui/components/tree/TreePanel.html | 66 +++++++
.../wicket/ui/components/tree/TreePanel.java | 54 ++++--
.../ui/components/tree/TreePanelFactories.java | 14 +-
13 files changed, 519 insertions(+), 84 deletions(-)
diff --git a/core/applib/src/main/java/org/apache/isis/applib/tree/LazyTreeNode.java b/core/applib/src/main/java/org/apache/isis/applib/tree/LazyTreeNode.java
index e464373..1d75d33 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/tree/LazyTreeNode.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/tree/LazyTreeNode.java
@@ -21,15 +21,17 @@ package org.apache.isis.applib.tree;
import java.util.Objects;
import java.util.stream.Stream;
+import org.apache.isis.applib.annotation.Value;
import org.apache.isis.applib.internal.base._Lazy;
+@Value(semanticsProviderName="org.apache.isis.core.metamodel.facets.value.treenode.TreeNodeValueSemanticsProvider")
public class LazyTreeNode<T> implements TreeNode<T> {
private final T value;
private final Class<? extends TreeAdapter<T>> treeAdapterClass;
private final _Lazy<TreeAdapter<T>> treeAdapter = _Lazy.of(this::newTreeAdapter);
- static <T> TreeNode<T> of(T value, Class<? extends TreeAdapter<T>> treeAdapterClass) {
+ public static <T> TreeNode<T> of(T value, Class<? extends TreeAdapter<T>> treeAdapterClass) {
return new LazyTreeNode<T>(value, treeAdapterClass);
}
@@ -66,6 +68,7 @@ public class LazyTreeNode<T> implements TreeNode<T> {
;
}
+ @Override
public Class<? extends TreeAdapter<T>> getTreeAdapterClass() {
return treeAdapterClass;
}
@@ -77,7 +80,7 @@ public class LazyTreeNode<T> implements TreeNode<T> {
return treeAdapterClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException(
- String.format("failed to instanciate treeAdapter '%s'", treeAdapterClass.getName()), e);
+ String.format("failed to instantiate TreeAdapter '%s'", treeAdapterClass.getName()), e);
}
}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/tree/TreeNode.java b/core/applib/src/main/java/org/apache/isis/applib/tree/TreeNode.java
index 0b07924..e387c0c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/tree/TreeNode.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/tree/TreeNode.java
@@ -27,33 +27,33 @@ import java.util.stream.StreamSupport;
import javax.annotation.Nullable;
public interface TreeNode<T> {
-
+
// -- VALUE
-
+
public T getValue();
-
+
// -- PARENT
-
+
public @Nullable TreeNode<T> getParentIfAny();
-
+
// -- CHILDREN
-
+
public int getChildCount();
public Stream<TreeNode<T>> streamChildren();
-
+
// -- BASIC PREDICATES
-
+
public default boolean isRoot() {
return getParentIfAny() == null;
}
-
+
public default boolean isLeaf() {
return getChildCount() == 0;
}
// -- CONSTRUCTION
-
+
/**
* Convenient shortcut.
* @param node
@@ -63,43 +63,52 @@ public interface TreeNode<T> {
public static <T> TreeNode<T> lazy(T node, Class<? extends TreeAdapter<T>> treeAdapterClass) {
return LazyTreeNode.of(node, treeAdapterClass);
}
-
+
// -- PARENT NODE ITERATION
-
+
public default Iterator<TreeNode<T>> iteratorHierarchyUp(){
return new TreeNode_iteratorHierarchyUp<>(this);
}
-
+
// -- PARENT NODE STREAMING
-
+
public default Stream<TreeNode<T>> streamHierarchyUp(){
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iteratorHierarchyUp(), Spliterator.ORDERED),
false); // not parallel
}
-
+
// -- CHILD NODE ITERATION
-
+
public default Iterator<TreeNode<T>> iteratorDepthFirst(){
return new TreeNode_iteratorDepthFirst<>(this);
}
-
+
public default Iterator<TreeNode<T>> iteratorBreadthFirst(){
return new TreeNode_iteratorBreadthFirst<>(this);
}
-
+
// -- CHILD NODE STREAMING
-
+
public default Stream<TreeNode<T>> streamDepthFirst(){
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iteratorDepthFirst(), Spliterator.ORDERED),
false); // not parallel
}
-
+
public default Stream<TreeNode<T>> streamBreadthFirst(){
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iteratorBreadthFirst(), Spliterator.ORDERED),
false); // not parallel
}
-
+
+ // -- LAZY NODE ADAPTING
+
+ /**
+ * @return
+ */
+ // [ahuber] Implementation Note: a class rather than an instance, because otherwise
+ // the adapter would need to be serializable for Wicket's trees to work correctly.
+ public Class<? extends TreeAdapter<T>> getTreeAdapterClass();
+
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacet.java
similarity index 56%
copy from core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacet.java
index 7375410..90c1796 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacet.java
@@ -17,20 +17,11 @@
* under the License.
*/
-package org.apache.isis.viewer.wicket.ui.components.tree;
+package org.apache.isis.core.metamodel.facets.value.treenode;
-import org.apache.isis.viewer.wicket.model.models.ValueModel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.markup.MarkupComponent;
-import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.core.metamodel.facetapi.Facet;
-public class StandaloneTreePanel extends PanelAbstract<ValueModel> {
-
- private static final long serialVersionUID = 1L;
- private static final String ID_STANDALONE_VALUE = "standaloneValue";
-
- public StandaloneTreePanel(final String id, final ValueModel valueModel) {
- super(id, valueModel);
- add(new MarkupComponent(ID_STANDALONE_VALUE, getModel()));
- }
+public interface TreeNodeValueFacet extends Facet {
+
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacetUsingSemanticsProviderFactory.java
similarity index 52%
copy from core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacetUsingSemanticsProviderFactory.java
index 7375410..53281e7 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueFacetUsingSemanticsProviderFactory.java
@@ -17,20 +17,24 @@
* under the License.
*/
-package org.apache.isis.viewer.wicket.ui.components.tree;
+package org.apache.isis.core.metamodel.facets.value.treenode;
-import org.apache.isis.viewer.wicket.model.models.ValueModel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.markup.MarkupComponent;
-import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.applib.tree.TreeNode;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueFacetUsingSemanticsProviderFactory;
-public class StandaloneTreePanel extends PanelAbstract<ValueModel> {
-
- private static final long serialVersionUID = 1L;
- private static final String ID_STANDALONE_VALUE = "standaloneValue";
-
- public StandaloneTreePanel(final String id, final ValueModel valueModel) {
- super(id, valueModel);
- add(new MarkupComponent(ID_STANDALONE_VALUE, getModel()));
- }
+@SuppressWarnings("rawtypes")
+public class TreeNodeValueFacetUsingSemanticsProviderFactory
+extends ValueFacetUsingSemanticsProviderFactory<TreeNode> {
+
+ @Override
+ public void process(final ProcessClassContext processClassContext) {
+ final Class<?> type = processClassContext.getCls();
+ final FacetHolder holder = processClassContext.getFacetHolder();
+ if (!TreeNode.class.isAssignableFrom(type)) {
+ return;
+ }
+ addFacets(new TreeNodeValueSemanticsProvider(holder, getContext()));
+ }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueSemanticsProvider.java
new file mode 100644
index 0000000..66f3a8b
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/value/treenode/TreeNodeValueSemanticsProvider.java
@@ -0,0 +1,133 @@
+/*
+ * 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.isis.core.metamodel.facets.value.treenode;
+
+import org.apache.isis.applib.adapters.DefaultsProvider;
+import org.apache.isis.applib.adapters.EncoderDecoder;
+import org.apache.isis.applib.adapters.Parser;
+import org.apache.isis.applib.internal.memento._Mementos;
+import org.apache.isis.applib.internal.memento._Mementos.Memento;
+import org.apache.isis.applib.internal.memento._Mementos.SerializingAdapter;
+import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
+import org.apache.isis.applib.tree.TreeNode;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueSemanticsProviderAndFacetAbstract;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+
+@SuppressWarnings("rawtypes")
+public class TreeNodeValueSemanticsProvider extends ValueSemanticsProviderAndFacetAbstract<TreeNode>
+implements TreeNodeValueFacet {
+
+ private static final int TYPICAL_LENGTH = 0;
+
+ private static Class<? extends Facet> type() {
+ return TreeNodeValueFacet.class;
+ }
+
+ private static final TreeNode DEFAULT_VALUE = null;
+ private static final Class<TreeNode> VALUE_TYPE = TreeNode.class;
+
+ /**
+ * Required because implementation of {@link Parser} and
+ * {@link EncoderDecoder}.
+ */
+ public TreeNodeValueSemanticsProvider() {
+ this(null, null);
+ }
+
+ public TreeNodeValueSemanticsProvider(final FacetHolder holder, final ServicesInjector context) {
+ super(type(), holder, VALUE_TYPE, TYPICAL_LENGTH, null, Immutability.IMMUTABLE,
+ EqualByContent.NOT_HONOURED, DEFAULT_VALUE, context);
+ }
+
+ @Override
+ public String titleString(final Object object) {
+ return object != null ? ((TreeNode<?>)object).toString() : "[null]"; //TODO implement
+ }
+
+ @Override
+ public String titleStringWithMask(final Object value, final String usingMask) {
+ return titleString(value);
+ }
+
+ // //////////////////////////////////////////////////////////////////
+ // Parser
+ // //////////////////////////////////////////////////////////////////
+
+ @Override
+ public Parser<TreeNode> getParser() {
+ return null;
+ }
+
+ // //////////////////////////////////////////////////////////////////
+ // DefaultsProvider
+ // //////////////////////////////////////////////////////////////////
+
+ @Override
+ public DefaultsProvider<TreeNode> getDefaultsProvider() {
+ return null;
+ }
+
+ // //////////////////////////////////////////////////////////////////
+ // EncoderDecoder
+ // //////////////////////////////////////////////////////////////////
+
+ @Override
+ protected String doEncode(final Object object) {
+ TreeNode<?> treeNode = (TreeNode<?>)object;
+
+ final Memento memento = newMemento();
+ memento.put("primaryValue", treeNode.getValue());
+ memento.put("adapterClass", treeNode.getTreeAdapterClass());
+ return memento.asString();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected TreeNode<?> doRestore(final String input) {
+ final Memento memento = parseMemento(input);
+ return TreeNode.lazy(
+ memento.get("primaryValue", Object.class),
+ memento.get("adapterClass", Class.class));
+ }
+
+ // /////// toString ///////
+
+ @Override
+ public String toString() {
+ return "TreeNodeValueSemanticsProvider";
+ }
+
+ // -- HELPER
+
+ private _Mementos.Memento newMemento(){
+ final UrlEncodingService codec = getServicesInjector().lookupService(UrlEncodingService.class);
+ final SerializingAdapter serializer = getServicesInjector().lookupService(SerializingAdapter.class);
+ return _Mementos.create(codec, serializer);
+ }
+
+ private _Mementos.Memento parseMemento(String input){
+ final UrlEncodingService codec = getServicesInjector().lookupService(UrlEncodingService.class);
+ final SerializingAdapter serializer = getServicesInjector().lookupService(SerializingAdapter.class);
+ return _Mementos.parse(codec, serializer, input);
+ }
+
+}
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
index 2e03d81..52c2c44 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java
@@ -200,9 +200,10 @@ public class ComponentFactoryRegistrarDefault implements ComponentFactoryRegistr
protected void addComponentFactoriesForScalar(final ComponentFactoryList componentFactories) {
+ componentFactories.add(TreePanelFactories.parented());
+
componentFactories.add(new ReferencePanelFactory());
componentFactories.add(MarkupPanelFactories.parented());
- componentFactories.add(TreePanelFactories.parented());
componentFactories.add(new BooleanPanelFactory());
componentFactories.add(new BytePanelFactory());
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/tree/TreeViewModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/tree/TreeViewModel.java
index 7e75eb9..bb89d1c 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/tree/TreeViewModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/tree/TreeViewModel.java
@@ -3,6 +3,7 @@ package org.apache.isis.viewer.wicket.model.models.tree;
import org.apache.isis.applib.tree.TreeNode;
import org.apache.isis.viewer.wicket.model.models.ModelAbstract;
+@Deprecated //[ahuber] temporary
public class TreeViewModel extends ModelAbstract<TreeNode<Object>> {
private static final long serialVersionUID = 1L;
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
new file mode 100644
index 0000000..021d447
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
@@ -0,0 +1,209 @@
+package org.apache.isis.viewer.wicket.ui.components.tree;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.isis.applib.internal.collections._Lists;
+import org.apache.isis.applib.tree.TreeAdapter;
+import org.apache.isis.applib.tree.TreeNode;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.ModelAbstract;
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.models.ValueModel;
+import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAndTitlePanel;
+import org.apache.wicket.Component;
+import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider;
+import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree;
+import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+
+class IsisToWicketTreeAdapter {
+
+ public static EntityTree adapt(String id, ValueModel valueModel) {
+ return new EntityTree(id, toITreeProvider( valueModel ));
+ }
+
+ public static EntityTree adapt(String id, ScalarModel scalarModel) {
+ return new EntityTree(id, toITreeProvider( scalarModel ));
+ }
+
+ // -- RENDERING
+
+ private static class EntityTree extends NestedTree<EntityModel> {
+
+ private static final long serialVersionUID = 1L;
+
+ public EntityTree(String id, ITreeProvider<EntityModel> provider) {
+ super(id, provider);
+ add(new WindowsTheme()); // TODO not required if Isis provides it's own css styles for tree-nodes
+ }
+
+ /**
+ * To use a custom component for the representation of a node's content we override this method.
+ */
+ @Override
+ protected Component newContentComponent(String id, IModel<EntityModel> node) {
+ final EntityModel entityModel = node.getObject();
+ return new EntityIconAndTitlePanel(id, entityModel);
+ }
+
+
+ }
+
+ // -- HELPER
+
+ private static class EntitiyModelTreeAdapter implements TreeAdapter<EntityModel>, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final Class<? extends TreeAdapter> treeAdapterClass;
+ private transient TreeAdapter wrappedTreeAdapter;
+
+ private EntitiyModelTreeAdapter(Class<? extends TreeAdapter> treeAdapterClass) {
+ this.treeAdapterClass = treeAdapterClass;
+ }
+
+ private TreeAdapter wrappedTreeAdapter() {
+ if(wrappedTreeAdapter!=null) {
+ return wrappedTreeAdapter;
+ }
+ try {
+ return wrappedTreeAdapter = treeAdapterClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException("failed to instantiate tree adapter", e);
+ }
+ }
+
+ @Override
+ public Optional<EntityModel> parentOf(EntityModel entityModel) {
+ if(entityModel==null) {
+ return Optional.empty();
+ }
+ return wrappedTreeAdapter().parentOf(unwrap(entityModel))
+ .map(this::wrap);
+ }
+
+ @Override
+ public int childCountOf(EntityModel entityModel) {
+ if(entityModel==null) {
+ return 0;
+ }
+ return wrappedTreeAdapter().childCountOf(unwrap(entityModel));
+ }
+
+ @Override
+ public Stream<EntityModel> childrenOf(EntityModel entityModel) {
+ if(entityModel==null) {
+ return Stream.empty();
+ }
+ return wrappedTreeAdapter().childrenOf(unwrap(entityModel))
+ .map(this::wrap);
+ }
+
+ private EntityModel wrap(Object pojo) {
+ Objects.requireNonNull(pojo);
+ return new EntityModel(persistenceSession().getAdapterFor(pojo));
+ }
+
+ private Object unwrap(EntityModel model) {
+ Objects.requireNonNull(model);
+ return model.getObject().getObject();
+ }
+
+ private PersistenceSession persistenceSession() {
+ return IsisContext.getSessionFactory().getCurrentSession().getPersistenceSession();
+ }
+
+ }
+
+
+ private static class EntityModelTreeProvider implements ITreeProvider<EntityModel> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final EntityModel primaryValue;
+ private final EntitiyModelTreeAdapter treeAdapter;
+
+ private EntityModelTreeProvider(EntityModel primaryValue, EntitiyModelTreeAdapter treeAdapter) {
+ this.primaryValue = primaryValue;
+ this.treeAdapter = treeAdapter;
+ }
+
+ @Override
+ public void detach() {
+ }
+
+ @Override
+ public Iterator<? extends EntityModel> getRoots() {
+ return _Lists.singleton(primaryValue).iterator();
+ }
+
+ @Override
+ public boolean hasChildren(EntityModel node) {
+ return treeAdapter.childCountOf(node)>0;
+ }
+
+ @Override
+ public Iterator<? extends EntityModel> getChildren(EntityModel node) {
+ return treeAdapter.childrenOf(node).iterator();
+ }
+
+ @Override
+ public IModel<EntityModel> model(final EntityModel entityModel) {
+ return new LoadableDetachableEntityModel(entityModel);
+ }
+
+ }
+
+ private static ITreeProvider<EntityModel> toITreeProvider(ModelAbstract<ObjectAdapter> model) {
+
+ final TreeNode tree = (TreeNode) model.getObject().getObject();
+ final EntitiyModelTreeAdapter wrappingTreeAdapter = new EntitiyModelTreeAdapter(tree.getTreeAdapterClass());
+
+ return new EntityModelTreeProvider(wrappingTreeAdapter.wrap(tree.getValue()), wrappingTreeAdapter);
+ }
+
+ private static class LoadableDetachableEntityModel extends LoadableDetachableModel<EntityModel> {
+ private static final long serialVersionUID = 1L;
+
+ private final Oid id;
+
+ public LoadableDetachableEntityModel(EntityModel eModel) {
+ super(eModel);
+
+ id = eModel.getObject().getOid();
+ }
+
+ @Override
+ protected EntityModel load() {
+ return null; //TODO [ahuber] load model by id, possibly not required
+ }
+
+ /**
+ * Important! Models must be identifiable by their contained object.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof EntityModel) {
+ return ((EntityModel) obj).getObject().getOid().equals(id);
+ }
+ return false;
+ }
+
+ /**
+ * Important! Models must be identifiable by their contained object.
+ */
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+ }
+
+}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.html
index cfd86c4..6f2a25b 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.html
@@ -25,9 +25,7 @@
<body>
<wicket:panel>
- <div wicket:id="standaloneTree">
-
- </div>
+ <div wicket:id="tree">[tree]</div>
</wicket:panel>
</body>
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
index 7375410..66ee3b2 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/StandaloneTreePanel.java
@@ -20,17 +20,17 @@
package org.apache.isis.viewer.wicket.ui.components.tree;
import org.apache.isis.viewer.wicket.model.models.ValueModel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.markup.MarkupComponent;
import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
public class StandaloneTreePanel extends PanelAbstract<ValueModel> {
- private static final long serialVersionUID = 1L;
- private static final String ID_STANDALONE_VALUE = "standaloneValue";
+ private static final long serialVersionUID = 1L;
+ private static final String ID_TREE = "tree";
+
+ public StandaloneTreePanel(final String id, final ValueModel valueModel) {
+ super(id, valueModel);
+ add(IsisToWicketTreeAdapter.adapt(ID_TREE, valueModel));
+ }
- public StandaloneTreePanel(final String id, final ValueModel valueModel) {
- super(id, valueModel);
- add(new MarkupComponent(ID_STANDALONE_VALUE, getModel()));
- }
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.html
new file mode 100644
index 0000000..ae0dfd5
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.html
@@ -0,0 +1,66 @@
+<?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>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:wicket="http://wicket.apache.org" xml:lang="en" lang="en">
+<body>
+
+ <!-- a stripped down copy of ScalarPanelTextFieldAbstract.html -->
+
+ <wicket:panel>
+ <div class="scalarNameAndValueComponentType"
+ wicket:id="scalarTypeContainer">
+
+ <div class="form-group" wicket:id="scalarIfRegular">
+
+ <label class="scalarName control-label" wicket:id="scalarName">[Label text]</label>
+ <span class="scalarValueWrapper">
+ <div class="tree-theme-windows">
+ <span>
+ <wicket:container wicket:id="scalarValueContainer" />
+ </span>
+ <span class="associatedActionLinksRight"
+ wicket:id="associatedActionLinksRight">[drop down]</span>
+ </div>
+ <span wicket:id="feedback" class="help-block" />
+ <span wicket:id="associatedActionLinksBelow" />
+ </span>
+ <div class="clearfix"></div>
+ </div>
+
+ <div class="tree-theme-windows">
+ <wicket:container wicket:id="scalarIfCompact"/>
+ </div>
+
+ </div>
+
+ <wicket:fragment wicket:id="textInlinePrompt">
+ <span wicket:id="scalarValue" />
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="textarea">
+ <textarea name="scalarValue"
+ class="form-control input-sm scalarValue" wicket:id="scalarValue" />
+ </wicket:fragment>
+
+ </wicket:panel>
+</body>
+</html>
+
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.java
index 8377bc0..2de3334 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanel.java
@@ -20,46 +20,60 @@
package org.apache.isis.viewer.wicket.ui.components.tree;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
+import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelTextFieldParseableAbstract;
+import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.Model;
-public class TreePanel extends ScalarPanelAbstract2 {
+/**
+ * Immutable tree, reuses the ScalarPanelTextField functionality without the need of its text field.
+ */
+public class TreePanel extends ScalarPanelTextFieldParseableAbstract {
+
+ private static final long serialVersionUID = 1L;
- public TreePanel(String id, ScalarModel scalarModel) {
+ public TreePanel(final String id, final ScalarModel scalarModel) {
super(id, scalarModel);
}
- private static final long serialVersionUID = 1L;
-
@Override
protected String getScalarPanelType() {
return "treePanel";
}
@Override
- protected InlinePromptConfig getInlinePromptConfig() {
- // TODO Auto-generated method stub
- return null;
- }
+ protected MarkupContainer createScalarIfRegularFormGroup() {
- @Override
- protected MarkupContainer createComponentForRegular() {
- // TODO Auto-generated method stub
- return null;
+ if(getModel().isEditMode()) {
+ // fallback to text editor
+ return super.createScalarIfRegularFormGroup();
+ }
+
+ final Component treeComponent = createTreeComponent("scalarValueContainer");
+
+ getTextField().setLabel(Model.of(getModel().getName()));
+
+ final FormGroup formGroup = new FormGroup(ID_SCALAR_IF_REGULAR, getTextField());
+ formGroup.add(treeComponent);
+
+ final String labelCaption = getRendering().getLabelCaption(getTextField());
+ final Label scalarName = createScalarName(ID_SCALAR_NAME, labelCaption);
+ formGroup.add(scalarName);
+
+ return formGroup;
}
@Override
protected Component createComponentForCompact() {
- // TODO Auto-generated method stub
- return null;
+ return createTreeComponent(ID_SCALAR_IF_COMPACT);
}
- @Override
- protected Component getScalarValueComponent() {
- // TODO Auto-generated method stub
- return null;
+ // -- HELPER
+
+ private Component createTreeComponent(String id) {
+ return IsisToWicketTreeAdapter.adapt(id, getModel());
}
-
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanelFactories.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanelFactories.java
index 70b0470..606c848 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanelFactories.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/TreePanelFactories.java
@@ -45,19 +45,22 @@ public class TreePanelFactories {
@Override
public ApplicationAdvice appliesTo(final IModel<?> model) {
- if (!(model instanceof ScalarModel))
+ if (!(model instanceof ScalarModel)) {
return ApplicationAdvice.DOES_NOT_APPLY;
+ }
final ScalarModel scalarModel = (ScalarModel) model;
- if(!scalarModel.isScalarTypeAnyOf(org.apache.isis.applib.tree.TreeNode.class))
+ if(!scalarModel.isScalarTypeSubtypingAnyOf(org.apache.isis.applib.tree.TreeNode.class)) {
return ApplicationAdvice.DOES_NOT_APPLY;
+ }
return appliesIf( !scalarModel.hasChoices() );
}
@Override
public final Component createComponent(final String id, final IModel<?> model) {
+
return new TreePanel(id, (ScalarModel) model);
}
}
@@ -73,12 +76,15 @@ public class TreePanelFactories {
@Override
public ApplicationAdvice appliesTo(final IModel<?> model) {
- if (!(model instanceof ValueModel))
+ if (!(model instanceof ValueModel)) {
return ApplicationAdvice.DOES_NOT_APPLY;
+ }
+
final ValueModel valueModel = (ValueModel) model;
final ObjectAdapter adapter = valueModel.getObject();
- if(adapter==null || adapter.getObject()==null)
+ if(adapter==null || adapter.getObject()==null) {
return ApplicationAdvice.DOES_NOT_APPLY;
+ }
return appliesIf( adapter.getObject() instanceof org.apache.isis.applib.tree.TreeNode );
}
--
To stop receiving notification emails like this one, please contact
ahuber@apache.org.