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 <[email protected]> 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));
