You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2026/01/22 09:26:27 UTC
(causeway) 01/01: CAUSEWAY-3957: [v2] adds table's action column (backport)
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3957-tablerow.action.backport
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 9bedbc8c377af9d92b55a705d2e6f93b75d4ccd8
Author: andi-huber <ah...@apache.org>
AuthorDate: Thu Jan 22 10:26:16 2026 +0100
CAUSEWAY-3957: [v2] adds table's action column (backport)
not yet wired to show up
---
.../applib/layout/grid/bootstrap/BSGrid.java | 1 +
.../core/metamodel/spec/feature/ObjectAction.java | 23 +++
.../spec/feature/ObjectActionContainer.java | 5 +
.../metamodel/spec/feature/ObjectAssociation.java | 26 ++-
.../specimpl/dflt/ObjectSpecificationDefault.java | 7 +
.../specimpl/dflt/_MembersAsColumns.java | 205 +++++++++++++++++++++
.../core/metamodel/util/WhereContexts.java | 24 ++-
.../viewer/wicket/model/models/ActionModel.java | 26 +++
...tionalLinksPanel.java => ActionLinksPanel.java} | 62 +++++--
.../AdditionalLinksAsDropDownPanel.java | 4 +-
.../AdditionalLinksAsListInlinePanel.java | 4 +-
.../entityactions/LinkAndLabelFactory.java | 2 +-
.../ui/components/collection/CollectionPanel.java | 2 +-
.../CollectionContentsAsAjaxTablePanel.java | 10 +-
.../ajaxtable/columns/ActionColumn.java | 123 +++++++++++++
.../columns/AssociationColumnAbstract.java | 4 +-
.../ajaxtable/columns/GenericColumnAbstract.java | 38 ++--
.../ajaxtable/columns/PluralColumn.java | 4 +-
.../ajaxtable/columns/SingularColumn.java | 9 +-
.../ajaxtable/columns/TitleColumn.java | 12 +-
.../ajaxtable/columns/ToggleboxColumn.java | 4 +-
.../entity/collection/EntityCollectionPanel.java | 6 +-
.../components/entity/fieldset/PropertyGroup.java | 10 +-
.../entity/header/EntityHeaderPanel.java | 6 +-
.../wicket/ui/components/layout/bs/col/Col.java | 4 +-
.../ui/components/scalars/ScalarPanelAbstract.java | 10 +-
.../config/WicketViewerCssBundleInit.java | 4 +-
27 files changed, 558 insertions(+), 77 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/layout/grid/bootstrap/BSGrid.java b/api/applib/src/main/java/org/apache/causeway/applib/layout/grid/bootstrap/BSGrid.java
index e0f4ec9be22..852a2257225 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/layout/grid/bootstrap/BSGrid.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/layout/grid/bootstrap/BSGrid.java
@@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.stream.Stream;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
index a9d1ab61717..b4cda7f7fe8 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
@@ -39,8 +39,10 @@
import org.apache.causeway.core.metamodel.consent.Consent;
import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.causeway.core.metamodel.consent.InteractionResultSet;
+import org.apache.causeway.core.metamodel.facets.WhereValueFacet;
import org.apache.causeway.core.metamodel.facets.actions.action.choicesfrom.ChoicesFromFacet;
import org.apache.causeway.core.metamodel.facets.actions.position.ActionPositionFacet;
+import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet;
import org.apache.causeway.core.metamodel.facets.members.iconfa.FaFacet;
import org.apache.causeway.core.metamodel.facets.members.iconfa.FaLayersProvider;
import org.apache.causeway.core.metamodel.facets.members.layout.group.LayoutGroupFacet;
@@ -496,6 +498,27 @@ public static Predicate<ObjectAction> choicesFromAndHavingCollectionParameterFor
new ObjectActionParameter.Predicates.CollectionParameter(elementType)
));
}
+
+ /**
+ * Returns true if no {@link HiddenFacet} is found that vetoes visibility.
+ * <p>
+ * However, whereHidden={@link Where#ALL_TABLES} is used as default
+ * when no {@link HiddenFacet} is found.
+ *
+ * @see ObjectAssociation.Predicates#visibleAccordingToHiddenFacet(Where)
+ *
+ * @apiNote an alternative would be to prime the meta-model with fallback facets,
+ * however the current approach is more heap friendly
+ */
+ public static Predicate<ObjectAction> visibleAccordingToHiddenFacet(final Where whereContext) {
+ return (final ObjectAction act) -> act.lookupFacet(HiddenFacet.class)
+ .map(WhereValueFacet.class::cast)
+ .map(WhereValueFacet::where)
+ // whereHidden=ALL_TABLES is the default when not specified otherwise
+ .or(()->Optional.of(Where.ALL_TABLES))
+ .stream()
+ .noneMatch(whereHidden -> whereHidden.includes(whereContext));
+ }
// -- HELPER
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
index 9893050bbed..cb6ade78d65 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -140,6 +140,11 @@ default Stream<ObjectAction> streamAnyActions(final MixedIn mixedIn) {
* @param mixedIn - whether to include mixed in actions
*/
Stream<ObjectAction> streamRuntimeActions(MixedIn mixedIn);
+
+ /**
+ * Actions visible in dedicated actions-column, honoring order and visibility.
+ */
+ Stream<ObjectAction> streamActionsForColumnRendering(Identifier memberIdentifier);
// -- ACTION STREAM (NO INHERITANCE)
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
index b46a4083dc1..f6cb1f0d80f 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
@@ -41,6 +41,7 @@
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.util.Facets;
+import org.apache.causeway.core.metamodel.util.WhereContexts;
import static org.apache.causeway.applib.annotation.Where.PARENTED_TABLES;
import static org.apache.causeway.applib.annotation.Where.STANDALONE_TABLES;
@@ -160,12 +161,6 @@ public static Predicate<ObjectAssociation> staticallyVisible(final Where where)
};
}
- static Where whereContextFor(final Identifier memberIdentifier) {
- return memberIdentifier.type().isAction()
- ? STANDALONE_TABLES
- : PARENTED_TABLES;
- }
-
/**
* Returns true if no {@link HiddenFacet} is found that vetoes visibility.
*
@@ -176,9 +171,24 @@ static Where whereContextFor(final Identifier memberIdentifier) {
* @apiNote an alternative would be to prime the meta-model with fallback facets,
* however the current approach is more heap friendly
*/
+ @Deprecated
public static Predicate<ObjectAssociation> visibleAccordingToHiddenFacet(
final Identifier memberIdentifier) {
- val whereContext = whereContextFor(memberIdentifier);
+ return visibleAccordingToHiddenFacet(WhereContexts.collectionVariant(memberIdentifier));
+ }
+
+ /**
+ * Returns true if no {@link HiddenFacet} is found that vetoes visibility.
+ * <p>
+ * However, if it's a 1-to-Many, whereHidden={@link Where#ALL_TABLES} is used as default
+ * when no {@link HiddenFacet} is found.
+ *
+ * @see ObjectAction.Predicates#visibleAccordingToHiddenFacet(Where)
+ *
+ * @apiNote an alternative would be to prime the meta-model with fallback facets,
+ * however the current approach is more heap friendly
+ */
+ public static Predicate<ObjectAssociation> visibleAccordingToHiddenFacet(final Where whereContext) {
return (final ObjectAssociation assoc) -> assoc.lookupFacet(HiddenFacet.class)
.map(WhereValueFacet.class::cast)
.map(WhereValueFacet::where)
@@ -187,7 +197,7 @@ public static Predicate<ObjectAssociation> visibleAccordingToHiddenFacet(
.stream()
.noneMatch(whereHidden -> whereHidden.includes(whereContext));
}
-
+
public static Predicate<ObjectAssociation> referencesParent(
final @Nullable ObjectSpecification parentSpec) {
if(parentSpec == null) {
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index b2a396b0a53..d25af74ec73 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -321,6 +321,13 @@ public final Stream<ObjectAssociation> streamAssociationsForColumnRendering(
return new _AssociationsAsColumns(getMetaModelContext())
.streamAssociationsForColumnRendering(this, memberIdentifier, parentObject);
}
+
+ @Override
+ public Stream<ObjectAction> streamActionsForColumnRendering(
+ final Identifier memberIdentifier) {
+ return new _MembersAsColumns(getMetaModelContext())
+ .streamActionsForColumnRendering(this, memberIdentifier);
+ }
// -- DETERMINE INJECTABILITY
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java
new file mode 100644
index 00000000000..53dae802e0f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java
@@ -0,0 +1,205 @@
+/*
+ * 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.causeway.core.metamodel.specloader.specimpl.dflt;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.annotation.Where;
+import org.apache.causeway.applib.layout.component.PropertyLayoutData;
+import org.apache.causeway.applib.layout.grid.bootstrap.BSGrid;
+import org.apache.causeway.applib.services.tablecol.TableColumnOrderService;
+import org.apache.causeway.applib.services.tablecol.TableColumnVisibilityService;
+import org.apache.causeway.commons.internal.base._NullSafe;
+import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.commons.internal.collections._Maps;
+import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
+import org.apache.causeway.core.metamodel.facets.object.grid.GridFacet;
+import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.core.metamodel.util.WhereContexts;
+import org.springframework.lang.NonNull;
+
+import static org.apache.causeway.applib.annotation.Where.PARENTED_TABLES;
+import static org.apache.causeway.applib.annotation.Where.STANDALONE_TABLES;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+class _MembersAsColumns implements HasMetaModelContext {
+
+ @Getter(onMethod_ = {@Override})
+ private final MetaModelContext metaModelContext;
+
+ public final Stream<ObjectAction> streamActionsForColumnRendering(
+ final ObjectSpecification elementType,
+ final Identifier memberIdentifier) {
+ if(elementType.isValue()) return Stream.empty();
+
+ return elementType.streamRuntimeActions(MixedIn.INCLUDED)
+ .filter(ObjectAction.Predicates.visibleAccordingToHiddenFacet(WhereContexts.collectionVariant(memberIdentifier)))
+ .sorted((a, b)->a.getCanonicalFriendlyName().compareTo(b.getCanonicalFriendlyName()));
+ }
+
+ /**
+ * @param parentObject not used for standalone tables and allowed to be empty for parented ones
+ */
+ public final Stream<ObjectAssociation> streamAssociationsForColumnRendering(
+ final ObjectSpecification elementType,
+ final Identifier memberIdentifier,
+ final ManagedObject parentObject) {
+
+ // the type that has the properties and collections that make up this table's columns
+ var elementClass = elementType.getCorrespondingClass();
+
+ var parentSpecIfAny = parentObject.objSpec();
+
+ var assocById = _Maps.<String, ObjectAssociation>newLinkedHashMap();
+
+ elementType.streamAssociations(MixedIn.INCLUDED)
+ .filter(ObjectAssociation.Predicates.visibleAccordingToHiddenFacet(WhereContexts.collectionVariant(memberIdentifier)))
+ .filter(ObjectAssociation.Predicates.referencesParent(parentSpecIfAny).negate())
+ .filter(assoc->filterColumnsUsingSpi(assoc, elementClass)) // optional SPI to filter columns;
+ .forEach(assoc->assocById.put(assoc.getId(), assoc));
+
+ var assocIdsInOrder = _Lists.<String>newArrayList(assocById.keySet());
+
+ // sort by order of occurrence within associated layout, if any
+ propertyIdComparator(elementType)
+ .ifPresent(assocIdsInOrder::sort);
+
+ // optional SPI to reorder columns
+ sortColumnsUsingSpi(memberIdentifier, parentObject, assocIdsInOrder, elementClass);
+
+ // add all ordered columns to the table
+ return assocIdsInOrder.stream()
+ .map(assocById::get)
+ .filter(_NullSafe::isPresent);
+ }
+
+ // -- HELPER
+
+ private boolean filterColumnsUsingSpi(
+ final ObjectAssociation assoc,
+ final Class<?> elementType) {
+ return getServiceRegistry()
+ .select(TableColumnVisibilityService.class)
+ .stream()
+ .noneMatch(x -> x.hides(elementType, assoc.getId()));
+ }
+
+ // comparator based on grid facet, that is by order of occurrence within associated layout
+ private Optional<Comparator<String>> propertyIdComparator(
+ final @NonNull ObjectSpecification elementTypeSpec) {
+
+ // same code also appears in DomainObjectPage.
+ // we need to do this here otherwise any tables will render the columns in the wrong order until at least
+ // one object of that type has been rendered via DomainObjectPage.
+ var elementTypeGridFacet = elementTypeSpec.getFacet(GridFacet.class);
+
+ if(elementTypeGridFacet == null) return Optional.empty();
+
+ // the facet should always exist, in fact
+ // just enough to ask for the metadata.
+
+ // don't pass in any object, just need the meta-data
+ var elementTypeGrid = elementTypeGridFacet.getGrid(null);
+ if(elementTypeGrid ==null) return Optional.empty();
+
+ final Map<String, Integer> propertyIdOrderWithinGrid = new HashMap<>();
+ streamPropertyLayoutData((BSGrid)elementTypeGrid)
+ .map(PropertyLayoutData::getId)
+ .forEach(propertyId->{
+ propertyIdOrderWithinGrid.put(propertyId, propertyIdOrderWithinGrid.size());
+ });
+
+ // if propertyId is mentioned within grid, put into first 'half' ordered by
+ // occurrence within grid
+ // if propertyId is not mentioned within grid, put into second 'half' ordered by
+ // propertyId (String) in natural order
+ return Optional.of(Comparator
+ .<String>comparingInt(propertyId->
+ propertyIdOrderWithinGrid.getOrDefault(propertyId, Integer.MAX_VALUE))
+ .thenComparing(Comparator.naturalOrder()));
+ }
+
+ private Stream<PropertyLayoutData> streamPropertyLayoutData(BSGrid bsGrid) {
+ final var properties = new ArrayList<PropertyLayoutData>();
+ bsGrid.visit(new BSGrid.VisitorAdapter() {
+ @Override
+ public void visit(final PropertyLayoutData propertyLayoutData) {
+ properties.add(propertyLayoutData);
+ }
+ });
+ return properties.stream();
+ }
+
+ private void sortColumnsUsingSpi(
+ final Identifier memberIdentifier,
+ // not used for standalone tables, and allowed to be empty in parented ones
+ final ManagedObject parentObject,
+ final List<String> propertyIdsInOrder,
+ final Class<?> elementType) {
+
+ var tableColumnOrderServices = getServiceRegistry().select(TableColumnOrderService.class);
+ if(tableColumnOrderServices.isEmpty()) {
+ return;
+ }
+
+ var whereContext = whereContextFor(memberIdentifier);
+
+ tableColumnOrderServices.stream()
+ .map(tableColumnOrderService->
+ whereContext.inStandaloneTable()
+ ? tableColumnOrderService.orderStandalone(
+ elementType,
+ propertyIdsInOrder)
+ : tableColumnOrderService.orderParented(
+ parentObject.getPojo(),
+ memberIdentifier.memberLogicalName(),
+ elementType,
+ propertyIdsInOrder))
+ .filter(_NullSafe::isPresent)
+ .findFirst()
+ .filter(propertyReorderedIds->propertyReorderedIds!=propertyIdsInOrder) // skip if its the same object
+ .ifPresent(propertyReorderedIds->{
+ propertyIdsInOrder.clear();
+ propertyIdsInOrder.addAll(propertyReorderedIds);
+ });
+
+ }
+
+ static Where whereContextFor(final Identifier memberIdentifier) {
+ return memberIdentifier.type().isAction()
+ ? STANDALONE_TABLES
+ : PARENTED_TABLES;
+ }
+
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
similarity index 53%
copy from viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
copy to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
index f737a93e743..42b7fb7b96b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
@@ -16,16 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions;
+package org.apache.causeway.core.metamodel.util;
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.annotation.Where;
-public class AdditionalLinksAsDropDownPanel extends AdditionalLinksPanel {
+import lombok.experimental.UtilityClass;
- private static final long serialVersionUID = 1L;
+@UtilityClass
+public class WhereContexts {
- public AdditionalLinksAsDropDownPanel(final String id, final Can<LinkAndLabel> links) {
- super(id, links, Style.DROPDOWN);
+ /**
+ * Utility, that detects the collection variant (standalone or parented),
+ * based on the feature {@link Identifier} of the originating feature,
+ * that is, the feature is either a plural member or a plural action result.
+ */
+ public Where collectionVariant(final Identifier featureId) {
+ var whereContext = featureId.type().isAction()
+ ? Where.STANDALONE_TABLES
+ : Where.PARENTED_TABLES;
+ return whereContext;
}
+
}
diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java
index bde90e3193d..57f98fd91d1 100644
--- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java
@@ -31,6 +31,32 @@
public interface ActionModel
extends UiActionForm, FormExecutorContext, BookmarkableModel, IModel<ManagedObject> {
+ /**
+ * If underlying action, originates from an action-column, it has special page redirect semantics:
+ * <ul>
+ * <li>if action return is void or matches the originating table/collection's element-type, then just RELOAD page</li>
+ * <li>otherwise open action result page in NEW browser tab</li>
+ * </ul>
+ * @since CAUSEWAY-3815
+ */
+ public enum ColumnActionModifier {
+ /**
+ * don't interfere with the default action result route
+ */
+ NONE,
+ /**
+ * reload current page, irrespective of the action result
+ */
+ FORCE_STAY_ON_PAGE,
+ /**
+ * open the action result in a new (blank) browser tab or window
+ */
+ FORCE_NEW_BROWSER_WINDOW;
+ public boolean isNone() { return this == NONE; }
+ public boolean isForceStayOnPage() { return this == FORCE_STAY_ON_PAGE; }
+ public boolean isForceNewBrowserWindow() { return this == FORCE_NEW_BROWSER_WINDOW; }
+ }
+
/** Resets arguments to their fixed point default values
* @see ActionInteractionHead#defaults(org.apache.causeway.core.metamodel.interactions.managed.ManagedAction)
*/
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/ActionLinksPanel.java
similarity index 62%
rename from viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
rename to viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/ActionLinksPanel.java
index dd8d41e4e49..742bcbbde4f 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/ActionLinksPanel.java
@@ -19,13 +19,20 @@
package org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.wicket.MarkupContainer;
-
+import org.apache.causeway.applib.annotation.Where;
import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.causeway.viewer.wicket.model.models.ActionModel;
+import org.apache.causeway.viewer.wicket.model.models.ActionModelImpl;
+import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
+import org.apache.causeway.viewer.wicket.model.models.ActionModel.ColumnActionModifier;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelFactory.MenuLinkFactory;
import org.apache.causeway.viewer.wicket.ui.components.menuable.MenuablePanelAbstract;
import org.apache.causeway.viewer.wicket.ui.util.Wkt;
import org.apache.causeway.viewer.wicket.ui.util.WktComponents;
@@ -33,7 +40,7 @@
import lombok.val;
-public class AdditionalLinksPanel
+public abstract class ActionLinksPanel
extends MenuablePanelAbstract {
private static final long serialVersionUID = 1L;
@@ -43,27 +50,27 @@ public class AdditionalLinksPanel
private static final String ID_ADDITIONAL_LINK_TITLE = "additionalLinkTitle";
public static final String ID_ADDITIONAL_LINK = "additionalLink";
- public enum Style {
+ public enum ActionPanelStyle {
INLINE_LIST {
@Override
- AdditionalLinksPanel newPanel(final String id, final Can<LinkAndLabel> links) {
+ ActionLinksPanel newPanel(final String id, final Can<LinkAndLabel> links) {
return new AdditionalLinksAsListInlinePanel(id, links);
}
},
DROPDOWN {
@Override
- AdditionalLinksPanel newPanel(final String id, final Can<LinkAndLabel> links) {
+ ActionLinksPanel newPanel(final String id, final Can<LinkAndLabel> links) {
return new AdditionalLinksAsDropDownPanel(id, links);
}
};
- abstract AdditionalLinksPanel newPanel(String id, Can<LinkAndLabel> links);
+ abstract ActionLinksPanel newPanel(String id, Can<LinkAndLabel> links);
}
- public static AdditionalLinksPanel addAdditionalLinks(
+ public static ActionLinksPanel addAdditionalLinks(
final MarkupContainer markupContainer,
final String id,
final Can<LinkAndLabel> links,
- final Style style) {
+ final ActionPanelStyle style) {
if(links.isEmpty()) {
WktComponents.permanentlyHide(markupContainer, id);
return null;
@@ -71,10 +78,21 @@ public static AdditionalLinksPanel addAdditionalLinks(
return Wkt.add(markupContainer, style.newPanel(id, links));
}
- protected AdditionalLinksPanel(
+ public static Optional<ActionLinksPanel> actionLinks(
+ final String id,
+ final Can<ActionModel> actionModels,
+ final ActionPanelStyle style,
+ final Where renderWhere) {
+
+ return actionModels.isEmpty()
+ ? Optional.empty()
+ : Optional.of(style.newPanel(id, actionModels.map(act->linkAndLabel(act, renderWhere))));
+ }
+
+ protected ActionLinksPanel(
final String id,
final Can<LinkAndLabel> menuables,
- final Style style) {
+ final ActionPanelStyle style) {
super(id, menuables);
setOutputMarkupId(true);
@@ -83,7 +101,7 @@ protected AdditionalLinksPanel(
Wkt.listViewAdd(container, ID_ADDITIONAL_LINK_ITEM, listOfLinkAndLabels(), item->{
val linkAndLabel = item.getModelObject();
- item.addOrReplace(WktLinks.asAdditionalLink(item, ID_ADDITIONAL_LINK_TITLE, linkAndLabel, style==Style.DROPDOWN));
+ item.addOrReplace(WktLinks.asAdditionalLink(item, ID_ADDITIONAL_LINK_TITLE, linkAndLabel, style==ActionPanelStyle.DROPDOWN));
if (!linkAndLabel.isVisible()) {
Wkt.cssAppend(item, "hidden");
}
@@ -108,5 +126,27 @@ protected final List<LinkAndLabel> listOfLinkAndLabels() {
public final boolean hasAnyVisibleLink() {
return streamLinkAndLabels().anyMatch(linkAndLabel->linkAndLabel.getUiComponent().isVisible());
}
+
+ // -- HELPER
+
+ private static LinkAndLabel linkAndLabel(
+ ActionModel actionModel, Where renderWhere) {
+ //new LinkAndLabel(actionModel, new MenuLinkFactory());
+ return null;
+ }
+
+ private static LinkAndLabelFactory forEntityFromActionColumn(
+ final UiObjectWkt parentEntityModel,
+ final ColumnActionModifier columnActionModifier) {
+ return (ObjectAction action) -> LinkAndLabel.of(
+ ActionModelImpl.forEntity(
+ parentEntityModel,
+ action.getFeatureIdentifier(),
+ Where.ALL_TABLES,
+//TODO BACKPORT columnActionModifier,
+ null, null, null),
+ new MenuLinkFactory());
+ }
+
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
index f737a93e743..668ba5c8028 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsDropDownPanel.java
@@ -21,11 +21,11 @@
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
-public class AdditionalLinksAsDropDownPanel extends AdditionalLinksPanel {
+public class AdditionalLinksAsDropDownPanel extends ActionLinksPanel {
private static final long serialVersionUID = 1L;
public AdditionalLinksAsDropDownPanel(final String id, final Can<LinkAndLabel> links) {
- super(id, links, Style.DROPDOWN);
+ super(id, links, ActionPanelStyle.DROPDOWN);
}
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
index 359477b5db0..fce54177a81 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/AdditionalLinksAsListInlinePanel.java
@@ -21,11 +21,11 @@
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
-public class AdditionalLinksAsListInlinePanel extends AdditionalLinksPanel {
+public class AdditionalLinksAsListInlinePanel extends ActionLinksPanel {
private static final long serialVersionUID = 1L;
public AdditionalLinksAsListInlinePanel(final String id, final Can<LinkAndLabel> links) {
- super(id, links, Style.INLINE_LIST);
+ super(id, links, ActionPanelStyle.INLINE_LIST);
}
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelFactory.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelFactory.java
index fa9111179db..f771ab6dd4c 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelFactory.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelFactory.java
@@ -136,7 +136,7 @@ static class AdditionalLinkFactory implements ActionLinkUiComponentFactoryWkt {
private static final long serialVersionUID = 1L;
@Override
public ActionLink newActionLinkUiComponent(@NonNull final ActionModel actionModel) {
- return ActionLink.create(AdditionalLinksPanel.ID_ADDITIONAL_LINK, actionModel);
+ return ActionLink.create(ActionLinksPanel.ID_ADDITIONAL_LINK, actionModel);
}
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
index 2cbeaa9086e..f75ac57fdeb 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -96,7 +96,7 @@ public ToggleboxColumn getToggleboxColumn() {
val collModel = getModel();
val collMetaModel = collModel.getMetaModel();
toggleboxColumn = collMetaModel.hasAssociatedActionsWithChoicesFromThisCollection()
- ? Optional.of(new ToggleboxColumn(collModel.delegate()))
+ ? Optional.of(new ToggleboxColumn(collModel.getElementType(), collModel.delegate()))
: Optional.empty();
}
return toggleboxColumn.orElse(null);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index 87a4c2c34de..255451032a5 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -19,6 +19,7 @@
package org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable;
import java.util.List;
+import java.util.Objects;
import org.apache.wicket.Component;
import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
@@ -27,6 +28,7 @@
import org.apache.causeway.commons.internal.collections._Lists;
import org.apache.causeway.core.config.CausewayConfiguration.Viewer.Wicket;
import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
@@ -94,12 +96,15 @@ private void buildGui() {
: null;
val collectionModel = entityCollectionModel();
+ var elementType = Objects.requireNonNull(collectionModel.getElementType(),
+ ()->"invalid: CollectionModel without element type");
// first create property columns, so we know how many columns there are
addPropertyColumnsIfRequired(columns);
// prepend title column, which may have distinct rendering hints,
// based on whether there are any property columns or not
prependTitleColumn(
+ elementType,
columns,
collectionModel.getVariant(),
getWicketViewerSettings());
@@ -127,6 +132,7 @@ private MultiselectToggleProvider getMultiselectToggleProvider() {
}
private void prependTitleColumn(
+ final ObjectSpecification elementType,
final List<GenericColumn> columns,
final Variant variant,
final Wicket wktConfig) {
@@ -144,7 +150,7 @@ private void prependTitleColumn(
: -1 /* don't override */)
.build();
- columns.add(0, new TitleColumn(variant, contextBookmark, maxColumnTitleLength, opts));
+ columns.add(0, new TitleColumn(elementType, variant, contextBookmark, maxColumnTitleLength, opts));
}
private void addPropertyColumnsIfRequired(final List<GenericColumn> columns) {
@@ -172,6 +178,7 @@ private SingularColumn createSingularColumn(final OneToOneAssociation property)
final String parentTypeName = property.getDeclaringType().logicalTypeName();
return new SingularColumn(
+ collectionModel.getElementType(),
collectionModel.getVariant(),
Model.of(property.getCanonicalFriendlyName()),
property.getId(),
@@ -185,6 +192,7 @@ private PluralColumn createPluralColumn(final OneToManyAssociation collection) {
final String parentTypeName = collection.getDeclaringType().logicalTypeName();
return new PluralColumn(
+ collectionModel.getElementType(),
collectionModel.getVariant(),
Model.of(collection.getCanonicalFriendlyName()),
collection.getId(),
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java
new file mode 100644
index 00000000000..c254c424b08
--- /dev/null
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java
@@ -0,0 +1,123 @@
+/*
+ * 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.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns;
+
+import java.util.Optional;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.IModel;
+import org.springframework.lang.NonNull;
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.annotation.Where;
+import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
+import org.apache.causeway.viewer.wicket.model.models.ActionModel;
+import org.apache.causeway.viewer.wicket.model.models.ActionModel.ColumnActionModifier;
+import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
+import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowWkt;
+import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel.Variant;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.util.Wkt;
+
+public final class ActionColumn
+extends GenericColumnAbstract {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Optional<ActionColumn> create(
+ final @NonNull Identifier featureId,
+ final @NonNull ObjectSpecification elementType,
+ final @NonNull Variant collectionVariant) {
+ //BACKPORT skipped
+ //var wktConfig = elementType.getMetaModelContext().getConfiguration().getViewer().getWicket();
+ //if(!wktConfig.isActionColumnEnabled()) return Optional.empty();
+ //----
+
+ var actions = elementType.streamActionsForColumnRendering(featureId)
+ .collect(Can.toCan());
+ if(actions.isEmpty()) return Optional.empty();
+
+ return Optional.of(new ActionColumn(elementType, actions, collectionVariant));
+ }
+
+ private final Can<String> actionIds;
+ private transient Can<ObjectAction> actions;
+ private final Variant collectionVariant;
+
+ private ActionColumn(
+ final ObjectSpecification elementType,
+ final Can<ObjectAction> actionsForColumnRendering,
+ final Variant collectionVariant) {
+ super(elementType, "Actions");
+ this.actions = actionsForColumnRendering;
+ this.actionIds = actions.map(ObjectAction::getId);
+ this.collectionVariant = collectionVariant;
+ }
+
+ @Override
+ protected Component createCellComponent(
+ final String componentId, final DataRow dataRow, IModel<Boolean> dataRowToggle) {
+
+ //var dataRow = dataRowWkt.getObject();
+ var rowElement = dataRow.getRowElement();
+
+ var objectModel = UiObjectWkt.ofAdapter(rowElement);
+ var elementType = elementType();
+
+//TODO BACKPORT ...
+// var actionModels = actions().stream()
+// .map(act->ActionModel.forEntityFromActionColumn(act, objectModel,
+// determineColumnActionModifier(act, elementType)))
+// .collect(Can.toCan());
+//
+// return ActionLinksPanel.actionLinks(componentId, actionModels, ActionLinksPanel.ActionPanelStyle.DROPDOWN, Where.ALL_TABLES)
+// .map(Component.class::cast)
+// .orElseGet(()->Wkt.label(componentId, ""));
+ return new Label(componentId, "TODO");
+ }
+
+ // -- HELPER
+
+ private ColumnActionModifier determineColumnActionModifier(
+ final ObjectAction action,
+ final ObjectSpecification collectionElementType) {
+
+ // refreshing of standalone collections currently not supported
+ if(collectionVariant.isStandalone()) return ColumnActionModifier.FORCE_NEW_BROWSER_WINDOW;
+
+ return action.getElementType().isVoid()
+ || action.getElementType().isOfType(collectionElementType)
+ ? ColumnActionModifier.FORCE_STAY_ON_PAGE
+ : ColumnActionModifier.FORCE_NEW_BROWSER_WINDOW;
+ }
+
+ private Can<ObjectAction> actions() {
+ synchronized(this) {
+ if(actions==null) {
+ var elementType = elementType();
+ this.actions = actionIds.map(elementType::getActionElseFail);
+ }
+ }
+ return actions;
+ }
+
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
index 9d8da5a4fc4..2c4e03e65ce 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
@@ -26,6 +26,7 @@
import org.apache.causeway.commons.internal.base._Strings;
import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.causeway.viewer.wicket.ui.ComponentFactory;
import org.apache.causeway.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
@@ -53,6 +54,7 @@ public abstract class AssociationColumnAbstract
protected final String describedAs;
public AssociationColumnAbstract(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
final String sortProperty,
@@ -60,7 +62,7 @@ public AssociationColumnAbstract(
final String parentTypeName,
final Optional<String> describedAs) {
- super(columnNameModel, sortProperty);
+ super(elementType, columnNameModel, sortProperty);
this.collectionVariant = collectionVariant;
this.memberId = memberId;
this.parentTypeName = parentTypeName;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
index 5492b1e791d..4d4c9a4040d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
@@ -18,18 +18,10 @@
*/
package org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns;
-import org.apache.wicket.Application;
-import org.apache.wicket.Component;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
-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.markup.repeater.Item;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-
import org.apache.causeway.applib.services.i18n.TranslationContext;
import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowWkt;
@@ -38,6 +30,15 @@
import org.apache.causeway.viewer.wicket.ui.app.registry.HasComponentFactoryRegistry;
import org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanel;
import org.apache.causeway.viewer.wicket.ui.util.Wkt;
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+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.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
import lombok.val;
@@ -54,16 +55,22 @@ public abstract class GenericColumnAbstract
private static final long serialVersionUID = 1L;
private transient ComponentFactoryRegistry componentRegistry;
+ private final Class<?> elementClass;
+ private transient ObjectSpecification elementType;
protected GenericColumnAbstract(
+ final ObjectSpecification elementType,
final String columnName) {
- this(Model.of(columnName), null);
+ this(elementType, Model.of(columnName), null);
}
protected GenericColumnAbstract(
+ final ObjectSpecification elementType,
final IModel<String> columnNameModel,
final String sortColumn) {
super(columnNameModel, sortColumn);
+ this.elementType = elementType;
+ this.elementClass = elementType.getCorrespondingClass();
}
@Override
@@ -87,6 +94,15 @@ public final void populateItem(
protected abstract Component createCellComponent(
final String componentId, final DataRow dataRow, IModel<Boolean> dataRowToggle);
+
+ public final ObjectSpecification elementType() {
+ synchronized(this) {
+ if(elementType==null) {
+ this.elementType = MetaModelContext.instanceElseFail().specForTypeElseFail(elementClass);
+ }
+ }
+ return elementType;
+ }
protected ComponentFactory findComponentFactory(final UiComponentType uiComponentType, final IModel<?> model) {
return getComponentRegistry().findComponentFactory(uiComponentType, model);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
index 9cefb6e537c..36d58286613 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
@@ -31,6 +31,7 @@
import org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.interactive.DataColumn;
import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
@@ -62,6 +63,7 @@ public static class RenderOptions implements Serializable {
private final RenderOptions opts;
public PluralColumn(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
final String sortProperty,
@@ -69,7 +71,7 @@ public PluralColumn(
final String parentTypeName,
final Optional<String> describedAs,
final RenderOptions opts) {
- super(collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
+ super(elementType, collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
this.opts = opts;
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
index df5acf7e3f5..5eaa934c5db 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
@@ -20,14 +20,14 @@
import java.util.Optional;
-import org.apache.wicket.Component;
-import org.apache.wicket.model.IModel;
-
import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
import lombok.val;
@@ -37,13 +37,14 @@ public final class SingularColumn
private static final long serialVersionUID = 1L;
public SingularColumn(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
final String sortProperty,
final String propertyId,
final String parentTypeName,
final Optional<String> describedAs) {
- super(collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
+ super(elementType, collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
}
@Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
index 42491874bc4..66d29f8be73 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
@@ -18,18 +18,17 @@
*/
package org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns;
-import org.apache.wicket.Component;
-import org.apache.wicket.model.IModel;
-
-import org.springframework.lang.Nullable;
-
import org.apache.causeway.applib.services.bookmark.Bookmark;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel.Variant;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
import org.apache.causeway.viewer.wicket.model.models.ValueModel;
+import org.apache.wicket.Component;
+import org.apache.wicket.model.IModel;
+import org.springframework.lang.Nullable;
import lombok.val;
@@ -42,12 +41,13 @@ public final class TitleColumn
private final Bookmark contextBookmark;
public TitleColumn(
+ final ObjectSpecification elementType,
final Variant variant,
final Bookmark contextBookmark,
final int maxColumnTitleLength,
final ColumnAbbreviationOptions opts) {
- super(columnName(variant, maxColumnTitleLength)); // i18n
+ super(elementType, columnName(variant, maxColumnTitleLength)); // i18n
this.variant = variant;
this.contextBookmark = contextBookmark;
this.opts = opts;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
index cfcdeafaf29..3dacfa5351a 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
@@ -25,6 +25,7 @@
import org.apache.wicket.model.IModel;
import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.interactive.DataRow;
import org.apache.causeway.core.metamodel.tabular.interactive.DataTableInteractive;
import org.apache.causeway.viewer.wicket.ui.components.widgets.checkbox.ContainedToggleboxPanel;
@@ -48,8 +49,9 @@ static BulkToggle valueOf(final boolean b) {
private IModel<DataTableInteractive> dataTableModelHolder;
public ToggleboxColumn(
+ final ObjectSpecification elementType,
final IModel<DataTableInteractive> dataTableModelHolder) {
- super("");
+ super(elementType, "");
this.dataTableModelHolder = dataTableModelHolder;
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
index f7c89d6b069..d5660d57b62 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/collection/EntityCollectionPanel.java
@@ -36,7 +36,7 @@
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModelParented;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
import org.apache.causeway.viewer.wicket.model.util.ComponentHintKey;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.collection.CollectionPanel;
import org.apache.causeway.viewer.wicket.ui.components.collection.selector.CollectionPresentationSelectorHelper;
import org.apache.causeway.viewer.wicket.ui.components.collection.selector.CollectionPresentationSelectorPanel;
@@ -152,8 +152,8 @@ private void buildGui() {
.ifPresent(description->WktTooltips.addTooltip(labelComponent, description));
final Can<LinkAndLabel> links = collectionModel.getLinks();
- AdditionalLinksPanel.addAdditionalLinks(
- div, ID_ADDITIONAL_LINKS, links, AdditionalLinksPanel.Style.INLINE_LIST);
+ ActionLinksPanel.addAdditionalLinks(
+ div, ID_ADDITIONAL_LINKS, links, ActionLinksPanel.ActionPanelStyle.INLINE_LIST);
createSelectorDropdownPanel(collectionModel);
collectionPanel.setSelectorDropdownPanel(selectorDropdownPanel);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
index 70db27c6d7e..4c41c53bc0d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
@@ -42,7 +42,7 @@
import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelFactory;
import org.apache.causeway.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
import org.apache.causeway.viewer.wicket.ui.panels.HasDynamicallyVisibleContent;
@@ -111,17 +111,17 @@ private List<Component> buildGui() {
} else {
Wkt.labelAdd(panelHeading, ID_MEMBER_GROUP_NAME, fieldSet.getName());
- AdditionalLinksPanel.addAdditionalLinks(
+ ActionLinksPanel.addAdditionalLinks(
panelHeading, ID_ASSOCIATED_ACTION_LINKS_PANEL,
memberGroupActions
.filter(LinkAndLabel.isPositionedAt(ActionLayout.Position.PANEL)),
- AdditionalLinksPanel.Style.INLINE_LIST);
+ ActionLinksPanel.ActionPanelStyle.INLINE_LIST);
- AdditionalLinksPanel.addAdditionalLinks(
+ ActionLinksPanel.addAdditionalLinks(
panelHeading, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN,
memberGroupActions
.filter(LinkAndLabel.isPositionedAt(ActionLayout.Position.PANEL_DROPDOWN)),
- AdditionalLinksPanel.Style.DROPDOWN);
+ ActionLinksPanel.ActionPanelStyle.DROPDOWN);
}
// either add the built content, or hide entire
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
index 5b8a0d2cc43..36226a38037 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/entity/header/EntityHeaderPanel.java
@@ -26,7 +26,7 @@
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
import org.apache.causeway.viewer.wicket.ui.ComponentFactory;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelFactory;
import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract;
import org.apache.causeway.viewer.wicket.ui.util.WktComponents;
@@ -79,9 +79,9 @@ private void buildEntityActionsGui() {
.map(LinkAndLabelFactory.forEntity(model))
.collect(Can.toCan());
- AdditionalLinksPanel
+ ActionLinksPanel
.addAdditionalLinks(this, ID_ENTITY_ACTIONS, topLevelActions,
- AdditionalLinksPanel.Style.INLINE_LIST);
+ ActionLinksPanel.ActionPanelStyle.INLINE_LIST);
} else {
WktComponents.permanentlyHide(this, ID_ENTITY_ACTIONS);
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/layout/bs/col/Col.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/layout/bs/col/Col.java
index 2e2072bdd00..d5212cac77b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/layout/bs/col/Col.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/layout/bs/col/Col.java
@@ -41,7 +41,7 @@
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
import org.apache.causeway.viewer.wicket.ui.ComponentFactory;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelFactory;
import org.apache.causeway.viewer.wicket.ui.components.entity.collection.EntityCollectionPanelFactory.CollectionOwnerAndLayout;
import org.apache.causeway.viewer.wicket.ui.components.entity.fieldset.PropertyGroup;
@@ -135,7 +135,7 @@ private void buildGui() {
.collect(Can.toCan());
if (!visibleActions.isEmpty()) {
- AdditionalLinksPanel.addAdditionalLinks(actionOwner, actionIdToUse, visibleActions, AdditionalLinksPanel.Style.INLINE_LIST);
+ ActionLinksPanel.addAdditionalLinks(actionOwner, actionIdToUse, visibleActions, ActionLinksPanel.ActionPanelStyle.INLINE_LIST);
visible = true;
} else {
WktComponents.permanentlyHide(actionOwner, actionIdToUse);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index 8c1090f0582..0aedbef4780 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -56,7 +56,7 @@
import org.apache.causeway.viewer.commons.model.scalar.UiParameter;
import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
import org.apache.causeway.viewer.wicket.model.models.ScalarModel;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.FrameFragment;
import org.apache.causeway.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.RegularFrame;
import org.apache.causeway.viewer.wicket.ui.components.scalars.blobclob.CausewayBlobOrClobPanelAbstract;
@@ -612,15 +612,15 @@ private void addActionLinksBelowAndRight(
val linksBelow = linkAndLabels
.filter(LinkAndLabel.isPositionedAt(ActionLayout.Position.BELOW));
- AdditionalLinksPanel.addAdditionalLinks(
+ ActionLinksPanel.addAdditionalLinks(
labelIfRegular, RegularFrame.ASSOCIATED_ACTION_LINKS_BELOW.getContainerId(),
- linksBelow, AdditionalLinksPanel.Style.INLINE_LIST);
+ linksBelow, ActionLinksPanel.ActionPanelStyle.INLINE_LIST);
val linksRight = linkAndLabels
.filter(LinkAndLabel.isPositionedAt(ActionLayout.Position.RIGHT));
- AdditionalLinksPanel.addAdditionalLinks(
+ ActionLinksPanel.addAdditionalLinks(
labelIfRegular, RegularFrame.ASSOCIATED_ACTION_LINKS_RIGHT.getContainerId(),
- linksRight, AdditionalLinksPanel.Style.DROPDOWN);
+ linksRight, ActionLinksPanel.ActionPanelStyle.DROPDOWN);
}
/**
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WicketViewerCssBundleInit.java b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WicketViewerCssBundleInit.java
index 636f273b4b0..66c235e21fd 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WicketViewerCssBundleInit.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/WicketViewerCssBundleInit.java
@@ -28,7 +28,7 @@
import org.apache.causeway.commons.internal.collections._Sets;
import org.apache.causeway.viewer.wicket.model.causeway.WicketApplicationInitializer;
import org.apache.causeway.viewer.wicket.ui.ComponentFactory;
-import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.AdditionalLinksPanel;
+import org.apache.causeway.viewer.wicket.ui.components.actionmenu.entityactions.ActionLinksPanel;
import org.apache.causeway.viewer.wicket.ui.components.scalars.string.MultiLineStringPanel;
import org.apache.causeway.viewer.wicket.ui.panels.PanelUtil;
import org.apache.causeway.viewer.wicket.viewer.wicketapp.CausewayWicketApplication;
@@ -90,7 +90,7 @@ private void addSpecialCasesToCssBundle(final Set<CssResourceReference> referenc
// references.add(PanelUtil.cssResourceReferenceFor(LinksSelectorPanelAbstract.class));
// components without factories
- references.add(PanelUtil.cssResourceReferenceFor(AdditionalLinksPanel.class));
+ references.add(PanelUtil.cssResourceReferenceFor(ActionLinksPanel.class));
// non-conforming component factories
references.add(PanelUtil.cssResourceReferenceFor(MultiLineStringPanel.class));