This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch 3824-action.ellipsis in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 394bb05872fcbd8a858cb752ba950ca8e0457b49 Author: Andi Huber <[email protected]> AuthorDate: Sat Oct 26 11:18:18 2024 +0200 CAUSEWAY-3824: refactoring: consolidates menu action decoration --- .../model/action/decorator/UiActionDecorator.java | 46 ------- .../commons/model/decorators/ConfirmDecorator.java | 39 +++--- .../model/decorators/DisablingDecorator.java | 11 +- .../model/decorators/FormLabelDecorator.java | 26 +--- .../model/decorators/MenuActionDecorator.java | 72 +++++++++++ .../model/decorators/PrototypingDecorator.java | 12 +- .../commons/model/decorators/TooltipDecorator.java | 8 +- .../viewer/wicket/model/links/LinkAndLabel.java | 12 ++ .../actionmenu/serviceactions/CssMenuItem.java | 2 +- .../actionmenu/serviceactions/MenuActionPanel.java | 5 +- .../serviceactions/ServiceActionUtil.java | 33 ++---- .../components/actions/ActionParametersForm.java | 30 +++-- .../viewer/wicket/ui/util/WktDecorators.java | 132 ++++++++------------- .../causeway/viewer/wicket/ui/util/WktLinks.java | 20 ++-- .../viewer/wicket/ui/util/WktTooltips.java | 6 +- 15 files changed, 210 insertions(+), 244 deletions(-) diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java deleted file mode 100644 index 42cc87d8e6..0000000000 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.commons.model.action.decorator; - -import org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator; -import org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator; -import org.apache.causeway.viewer.commons.model.decorators.IconDecorator; -import org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator; -import org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * Decorates a click-able UI component of various type {@code <T>} based UiModels. - * - * @since 2.0.0 - * @param <T> - link component type, native to the viewer - */ -@Getter -@RequiredArgsConstructor -public class UiActionDecorator<T> { - - private final TooltipDecorator<T> tooltipDecorator; - private final DisablingDecorator<T> disableDecorator; - private final ConfirmDecorator<T> confirmDecorator; - private final PrototypingDecorator<T, T> prototypingDecorator; - private final IconDecorator<T, T> iconDecorator; - -} diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java index 7ba2a5a792..69d31f1445 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java @@ -22,15 +22,14 @@ import java.io.Serializable; import java.util.Optional; import org.apache.causeway.applib.services.i18n.TranslationContext; -import org.apache.causeway.applib.services.i18n.TranslationService; import org.apache.causeway.core.config.messages.MessageRegistry; +import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection; -import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.val; +import lombok.experimental.Accessors; @FunctionalInterface public interface ConfirmDecorator<T> { @@ -39,8 +38,8 @@ public interface ConfirmDecorator<T> { // -- DECORATION MODEL - @Getter - @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE) + @Getter @Accessors(fluent=true) //RECORD (java 16) + @AllArgsConstructor public static class ConfirmDecorationModel implements Serializable { private static final long serialVersionUID = 1L; @@ -51,28 +50,18 @@ public interface ConfirmDecorator<T> { final @NonNull String cancelLabel; final @NonNull UiPlacementDirection placement; - public static ConfirmDecorationModel areYouSure( - final TranslationService translationService, - final UiPlacementDirection placement) { + public static ConfirmDecorationModel areYouSure(final UiPlacementDirection placement) { - val context = TranslationContext.forClassName(MessageRegistry.class); + var translationService = MetaModelContext.translationServiceOrFallback(); + var context = TranslationContext.forClassName(MessageRegistry.class); + + var areYouSure = translationService.translate(context, MessageRegistry.MSG_ARE_YOU_SURE); + var confirm = translationService.translate(context, MessageRegistry.MSG_CONFIRM); + var cancel = translationService.translate(context, MessageRegistry.MSG_CANCEL); - val areYouSure = translate(translationService, context, MessageRegistry.MSG_ARE_YOU_SURE); - val confirm = translate(translationService, context, MessageRegistry.MSG_CONFIRM); - val cancel = translate(translationService, context, MessageRegistry.MSG_CANCEL); + var message = Optional.<String>empty(); // not used yet - val message = Optional.<String>empty(); // not used yet - - return of(areYouSure, message, confirm, cancel, placement); - } - - // -- HELPER - - private static String translate(final TranslationService translationService, final TranslationContext context, final String msg) { - if(translationService!=null) { - return translationService.translate(context, msg); - } - return msg; + return new ConfirmDecorationModel(areYouSure, message, confirm, cancel, placement); } } diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java index be9cb16a93..bb3d6cb06d 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java @@ -24,10 +24,10 @@ import java.util.Optional; import org.apache.causeway.core.metamodel.interactions.managed.InteractionVeto; import org.apache.causeway.core.metamodel.interactions.managed.MemberInteraction; -import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NonNull; -import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; @FunctionalInterface public interface DisablingDecorator<T> { @@ -36,8 +36,8 @@ public interface DisablingDecorator<T> { // -- DECORATION MODEL - @Getter - @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE) + @Getter @Accessors(fluent=true) //RECORD (java 16) + @AllArgsConstructor public static class DisablingDecorationModel implements Serializable { private static final long serialVersionUID = 1L; @@ -46,14 +46,13 @@ public interface DisablingDecorator<T> { public static Optional<DisablingDecorationModel> of(@NonNull final Optional<InteractionVeto> usabilityVeto) { return usabilityVeto - .map(veto->of(veto.getReasonAsString().orElse(null))); + .map(veto->new DisablingDecorationModel(veto.getReasonAsString().orElse(null))); } public static Optional<DisablingDecorationModel> of(@NonNull final MemberInteraction<?, ?> memberInteraction) { return of(memberInteraction.getInteractionVeto()); } - } } diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java index 6da048546c..fc4a9f4386 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java @@ -20,11 +20,9 @@ package org.apache.causeway.viewer.commons.model.decorators; import java.io.Serializable; -import org.springframework.lang.Nullable; - -import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; @FunctionalInterface public interface FormLabelDecorator<T> { @@ -33,29 +31,17 @@ public interface FormLabelDecorator<T> { // -- DECORATION MODEL - @Getter - @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE) + @Getter @Accessors(fluent=true) //RECORD (java 16) + @AllArgsConstructor public static class FormLabelDecorationModel implements Serializable { private static final long serialVersionUID = 1L; public static FormLabelDecorationModel mandatory(final boolean mandatory) { - /* used to be suffixed with ':' till 2.0.0-RC1; - * however, the question arises what to do in the label RIGHT position case; - * and so we concluded, that perhaps its better to remove the suffix colon - * all together */ - return of(mandatory, ""); + return new FormLabelDecorationModel(mandatory); } - /* not used - public static FormLabelDecorationModel mandatorySuffixed2( - final boolean mandatory, - final @Nullable String suffix) { - return of(mandatory, suffix); - } */ - - final boolean mandatoryMarker; - final @Nullable String suffix; + final boolean isMandatoryIndicatorShown; } diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java new file mode 100644 index 0000000000..9974822564 --- /dev/null +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java @@ -0,0 +1,72 @@ +/* + * 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.commons.model.decorators; + +import java.util.Optional; + +import org.apache.causeway.applib.Identifier; +import org.apache.causeway.applib.fa.FontAwesomeLayers; +import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; +import org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator.DisablingDecorationModel; +import org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator.PrototypingDecorationModel; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.val; +import lombok.experimental.Accessors; + +/** + * Decorates Actions that appear in drop-down menus. + * + * @param <T> primary UI component type to decorate + * @param <U> secondary UI component type to decorate + * @param <V> tertiary UI component type to decorate + */ +@FunctionalInterface +public interface MenuActionDecorator<T, U, V> { + + void decorate(T uiComponent1, U uiComponent2, V uiComponent3, MenuActionDecorationModel decorationModel); + + // -- DECORATION MODEL + + @Builder(builderMethodName = "builderInternal") + @Getter @Accessors(fluent=true) //RECORD (java 16) + @AllArgsConstructor + public static class MenuActionDecorationModel { + private final boolean isImmediateConfirmationRequired; + private final Identifier featureIdentifier; + private final Optional<DisablingDecorationModel> disabling; + private final Optional<PrototypingDecorationModel> prototyping; + private final Optional<FontAwesomeLayers> fontAwesomeLayers; + private final Optional<String> describedAs; + private final Optional<String> additionalCssClass; + + public static MenuActionDecorationModelBuilder builder(final ManagedAction managedAction) { + val action = managedAction.getAction(); + return builderInternal() + .prototyping(managedAction.getAction().isPrototype() + ? Optional.of(PrototypingDecorationModel.of(managedAction)) + : Optional.empty()) + .isImmediateConfirmationRequired(action.isImmediateConfirmationRequired()); + } + + } + +} diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java index f83c8fac85..882a147141 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java @@ -25,9 +25,9 @@ import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedMember; -import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; /** * @@ -43,8 +43,8 @@ public interface PrototypingDecorator<T, R> { // -- DECORATION MODEL - @Getter - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + @Getter @Accessors(fluent=true) //RECORD (java 16) + @AllArgsConstructor public static class PrototypingDecorationModel { private final Class<?> featureType; @@ -58,7 +58,6 @@ public interface PrototypingDecorator<T, R> { String featureFullLabel = String.format("%s: %s", managedAction.getMemberType(), managedAction.getId()); - return new PrototypingDecorationModel(featureType, featureShortLabel, featureFullLabel, managedAction.getAction()::streamFacets); } @@ -69,7 +68,6 @@ public interface PrototypingDecorator<T, R> { String featureFullLabel = String.format("%s: %s", managedMember.getMemberType(), managedMember.getId()); - return new PrototypingDecorationModel(featureType, featureShortLabel, featureFullLabel, managedMember.getElementType()::streamFacets); } @@ -78,8 +76,6 @@ public interface PrototypingDecorator<T, R> { return facetStreamProvider.get(); } - - } } diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java index e8a4e7581d..6bd884dbd9 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java @@ -27,7 +27,7 @@ import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection; import lombok.NonNull; -import lombok.Value; +import lombok.experimental.Accessors; @FunctionalInterface public interface TooltipDecorator<T> { @@ -36,7 +36,7 @@ public interface TooltipDecorator<T> { // -- DECORATION MODEL - @Value(staticConstructor = "of") + @lombok.Value @Accessors(fluent=true) //RECORD (java 16) public static class TooltipDecorationModel implements Serializable { private static final long serialVersionUID = 1L; @@ -48,14 +48,14 @@ public interface TooltipDecorator<T> { public static TooltipDecorationModel ofBody( final @NonNull UiPlacementDirection uiPlacementDirection, final @Nullable String body) { - return of(uiPlacementDirection, Optional.empty(), _Strings.nonEmpty(body).orElse("")); + return new TooltipDecorationModel(uiPlacementDirection, Optional.empty(), _Strings.nonEmpty(body).orElse("")); } public static TooltipDecorationModel ofTitleAndBody( final @NonNull UiPlacementDirection uiPlacementDirection, final @Nullable String title, final @Nullable String body) { - return of(uiPlacementDirection, _Strings.nonEmpty(title), _Strings.nonEmpty(body).orElse("")); + return new TooltipDecorationModel(uiPlacementDirection, _Strings.nonEmpty(title), _Strings.nonEmpty(body).orElse("")); } public static TooltipDecorationModel empty() { diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java index 96197317c0..b11cf7d16b 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java @@ -30,6 +30,7 @@ import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.viewer.commons.model.action.HasManagedAction; +import org.apache.causeway.viewer.commons.model.decorators.MenuActionDecorator.MenuActionDecorationModel; import org.apache.causeway.viewer.commons.model.mixin.HasUiComponent; import org.apache.causeway.viewer.wicket.model.models.ActionModel; @@ -93,6 +94,17 @@ implements return actionModel.getUsabilityConsent().isAllowed(); } + public MenuActionDecorationModel getMenuActionDecorationModel() { + return MenuActionDecorationModel + .builder(getManagedAction()) + .featureIdentifier(getFeatureIdentifier()) + .describedAs(getDescription()) + .disabling(getDisableUiModel()) + .additionalCssClass(getAdditionalCssClass()) + .fontAwesomeLayers(lookupFontAwesomeLayers(true)) + .build(); + } + // -- UTILITY public static Predicate<LinkAndLabel> isPositionedAt(final Position panel) { diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java index ff593f232b..535576b3fb 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java @@ -151,7 +151,7 @@ implements Menuable { // ... and show label, along with disabled reason linkAndLabel.getDisableUiModel().ifPresent(disableUiModel->{ - WktTooltips.addTooltip(label, disableUiModel.getReason()); + WktTooltips.addTooltip(label, disableUiModel.reason()); }); label.add(new AttributeModifier("class", Model.of("disabled"))); diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java index 34502c0b06..1323bed5e9 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java @@ -74,13 +74,12 @@ public abstract class MenuActionPanel extends PanelBase { private void addFolderItem(final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem) { final MarkupContainer parent = this; - ServiceActionUtil.addFolderItem(super.getMetaModelContext(), menuItem, listItem, parent); + ServiceActionUtil.addFolderItem(menuItem, listItem, parent); } private void addLeafItem(final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem) { final MarkupContainer parent = this; - ServiceActionUtil.addLeafItem( - super.getMetaModelContext(), menuItem, listItem, parent); + ServiceActionUtil.addLeafItem(menuItem, listItem, parent); } private void addSpacer(final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem) { diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java index 213d6132af..3cca611468 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java @@ -41,36 +41,27 @@ import lombok.val; import lombok.experimental.UtilityClass; @UtilityClass -//@Log4j2 -public final class ServiceActionUtil { +class ServiceActionUtil { - static void addLeafItem( - final MetaModelContext commonContext, + void addLeafItem( final CssMenuItem menuItem, final ListItem<CssMenuItem> listItem, final MarkupContainer parent) { - val actionUiModel = menuItem.getLinkAndLabel(); - val menuItemActionLink = actionUiModel.getUiComponent(); - val menuItemLabel = Wkt.labelAdd(menuItemActionLink, "menuLinkLabel", menuItem.getName()); - - WktDecorators.getActionLink().decorateMenuItem( - listItem, - actionUiModel, - commonContext.getTranslationService()); + var linkAndLabel = menuItem.getLinkAndLabel(); + var menuItemActionLink = linkAndLabel.getUiComponent(); + var menuItemLabel = Wkt.labelAdd(menuItemActionLink, "menuLinkLabel", menuItem.getName()); - val faLayers = actionUiModel.lookupFontAwesomeLayers(true); - WktDecorators.getIcon().decorate(menuItemLabel, faLayers); - WktDecorators.getMissingIcon().decorate(menuItemActionLink, faLayers); + WktDecorators.getActionLink() + .decorate(listItem, menuItemActionLink, menuItemLabel, linkAndLabel.getMenuActionDecorationModel()); - val leafItem = new Fragment("content", "leafItem", parent); + var leafItem = new Fragment("content", "leafItem", parent); leafItem.add(menuItemActionLink); listItem.add(leafItem); } - static void addFolderItem( - final MetaModelContext commonContext, + void addFolderItem( final CssMenuItem subMenuItem, final ListItem<CssMenuItem> listItem, final MarkupContainer parent) { @@ -87,9 +78,9 @@ public final class ServiceActionUtil { CssMenuItem menuItem = listItem.getModelObject(); if (menuItem.hasSubMenuItems()) { - addFolderItem(commonContext, menuItem, item, parent); + addFolderItem(menuItem, item, parent); } else { - addLeafItem(commonContext, menuItem, item, parent); + addLeafItem(menuItem, item, parent); } }); @@ -137,7 +128,7 @@ public final class ServiceActionUtil { } } - public static void buildMenu( + void buildMenu( final MetaModelContext commonContext, final MenuUiModel menuUiModel, final Consumer<CssMenuItem> onNewMenuItem) { diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java index a85db8ff9a..00bb3a11c0 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java @@ -44,8 +44,6 @@ import org.apache.causeway.viewer.wicket.ui.panels.PromptFormAbstract; import org.apache.causeway.viewer.wicket.ui.util.Wkt; import org.apache.causeway.viewer.wicket.ui.util.WktDecorators; -import lombok.val; - import de.agilecoders.wicket.extensions.markup.html.bootstrap.confirmation.ConfirmationBehavior; class ActionParametersForm @@ -66,9 +64,9 @@ extends PromptFormAbstract<ActionModel> { @Override protected void addParameters() { - val actionModel = actionModel(); + var actionModel = actionModel(); - val repeatingView = + var repeatingView = Wkt.add(this, new RepeatingView(ActionParametersFormPanel.ID_ACTION_PARAMETERS)); paramPanels.clear(); @@ -77,7 +75,7 @@ extends PromptFormAbstract<ActionModel> { .map(UiParameterWkt.class::cast) .forEach(paramModel->{ - val container = Wkt.containerAdd(repeatingView, repeatingView.newChildId()); + var container = Wkt.containerAdd(repeatingView, repeatingView.newChildId()); newParamPanel(container, paramModel, paramPanels::add); @@ -91,10 +89,10 @@ extends PromptFormAbstract<ActionModel> { final UiParameterWkt paramModel, final Consumer<ScalarPanelAbstract> onNewScalarPanel) { - val scalarParamModel = ScalarParameterModel.wrap(paramModel); + var scalarParamModel = ScalarParameterModel.wrap(paramModel); // returned ScalarPanelAbstract should already have added any associated LinkAndLabel(s) - val component = getComponentFactoryRegistry() + var component = getComponentFactoryRegistry() .addOrReplaceComponent(container, ActionParametersFormPanel.ID_SCALAR_NAME_AND_VALUE, UiComponentType.SCALAR_NAME_AND_VALUE, scalarParamModel); @@ -118,11 +116,11 @@ extends PromptFormAbstract<ActionModel> { * @param button The button which action should be confirmed */ private void applyAreYouSure(final AjaxButton button) { - val actionModel = actionModel(); - val action = actionModel.getAction(); + var actionModel = actionModel(); + var action = actionModel.getAction(); if (action.getSemantics().isAreYouSure()) { - val confirmUiModel = ConfirmDecorationModel.areYouSure(getTranslationService(), UiPlacementDirection.BOTTOM); + var confirmUiModel = ConfirmDecorationModel.areYouSure(UiPlacementDirection.BOTTOM); WktDecorators.getConfirm().decorate(button, confirmUiModel); } } @@ -130,10 +128,10 @@ extends PromptFormAbstract<ActionModel> { @Override public void onUpdate(final AjaxRequestTarget target, final ScalarPanelAbstract scalarPanelUpdated) { - val actionModel = actionModel(); - val updatedParamModel = (UiParameter)scalarPanelUpdated.getModel(); - val paramNegotiationModel = updatedParamModel.getParameterNegotiationModel(); - val pendingParamModels = actionModel.streamPendingParamUiModels().collect(Can.toCan()); + var actionModel = actionModel(); + var updatedParamModel = (UiParameter)scalarPanelUpdated.getModel(); + var paramNegotiationModel = updatedParamModel.getParameterNegotiationModel(); + var pendingParamModels = actionModel.streamPendingParamUiModels().collect(Can.toCan()); final int paramIndexOfUpdated = updatedParamModel.getParameterIndex(); _Xray.beforeParamFormUpdate(paramIndexOfUpdated, paramNegotiationModel); @@ -148,8 +146,8 @@ extends PromptFormAbstract<ActionModel> { Repaint.required(wasValueChanged); _Xray.reassessedDefault(paramIndexForReassessment, paramNegotiationModel); - val paramPanel = paramPanels.get(paramIndexForReassessment); - val paramModel = pendingParamModels.getElseFail(paramIndexForReassessment); + var paramPanel = paramPanels.get(paramIndexForReassessment); + var paramModel = pendingParamModels.getElseFail(paramIndexForReassessment); /* repaint is required, either because of a changed value during reassessment above * or because visibility or usability have changed */ paramRepaint = paramRepaint.max( diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java index d24c86f77c..6020a52080 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java @@ -21,27 +21,25 @@ package org.apache.causeway.viewer.wicket.ui.util; import java.util.Optional; import org.apache.wicket.Component; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; +import org.apache.wicket.markup.html.list.ListItem; import org.apache.causeway.applib.fa.FontAwesomeLayers; -import org.apache.causeway.applib.services.i18n.TranslationService; -import org.apache.causeway.commons.internal.base._Casts; -import org.apache.causeway.commons.internal.base._Strings; -import org.apache.causeway.viewer.commons.model.action.decorator.UiActionDecorator; +import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator; import org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator.ConfirmDecorationModel; import org.apache.causeway.viewer.commons.model.decorators.DangerDecorator; import org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator; import org.apache.causeway.viewer.commons.model.decorators.FormLabelDecorator; import org.apache.causeway.viewer.commons.model.decorators.IconDecorator; +import org.apache.causeway.viewer.commons.model.decorators.MenuActionDecorator; import org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator; -import org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator.PrototypingDecorationModel; import org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator; import org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator.TooltipDecorationModel; import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection; -import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel; +import org.apache.causeway.viewer.wicket.model.links.Menuable; import org.apache.causeway.viewer.wicket.ui.components.actionmenu.FontAwesomeBehavior; import org.apache.causeway.viewer.wicket.ui.util.BootstrapConstants.ButtonSemantics; @@ -52,9 +50,6 @@ import lombok.experimental.UtilityClass; import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig.Placement; import de.agilecoders.wicket.extensions.markup.html.bootstrap.confirmation.ConfirmationConfig; -/** - * - */ @UtilityClass public class WktDecorators { @@ -77,13 +72,9 @@ public class WktDecorators { public final static class FormLabel implements FormLabelDecorator<Component> { @Override public void decorate(final Component uiComponent, final FormLabelDecorationModel decorationModel) { - if(decorationModel.isMandatoryMarker()) { + if(decorationModel.isMandatoryIndicatorShown()) { Wkt.cssAppend(uiComponent, "mandatory"); } - if(_Strings.isNotEmpty(decorationModel.getSuffix())) { - final IModel<String> labelModel = _Casts.uncheckedCast(uiComponent.getDefaultModel()); - uiComponent.setDefaultModel(Model.of(labelModel.getObject() + decorationModel.getSuffix())); - } uiComponent.setEscapeModelStrings(true); } } @@ -99,7 +90,7 @@ public class WktDecorators { @Override public void decorate(final Component uiComponent, final DisablingDecorationModel decorationModel) { val tooltipDecorationModel = TooltipDecorationModel - .ofBody(UiPlacementDirection.BOTTOM, decorationModel.getReason()); + .ofBody(UiPlacementDirection.BOTTOM, decorationModel.reason()); getTooltip().decorate(uiComponent, tooltipDecorationModel); Wkt.cssAppend(uiComponent, "disabled"); @@ -120,12 +111,12 @@ public class WktDecorators { public void decorate(final Component uiComponent, final ConfirmDecorationModel decorationModel) { val confirmationConfig = new ConfirmationConfig() - .withTitle(decorationModel.getTitle()) - .withBtnOkLabel(decorationModel.getOkLabel()) - .withBtnCancelLabel(decorationModel.getCancelLabel()) + .withTitle(decorationModel.title()) + .withBtnOkLabel(decorationModel.okLabel()) + .withBtnCancelLabel(decorationModel.cancelLabel()) .withBtnOkClass(ButtonSemantics.DANGER.fullButtonCss()) .withBtnCancelClass(ButtonSemantics.SECONDARY.fullButtonCss()) - .withPlacement(Placement.valueOf(decorationModel.getPlacement().name().toLowerCase())); + .withPlacement(Placement.valueOf(decorationModel.placement().name().toLowerCase())); Wkt.behaviorAddConfirm(uiComponent, confirmationConfig); @@ -167,67 +158,48 @@ public class WktDecorators { // -- ADVANCED DECORATOR CLASSES - public final static class ActionLink extends UiActionDecorator<Component> { + public final static class ActionLink + implements MenuActionDecorator<ListItem<? extends Menuable>, AjaxLink<ManagedObject>, Label> { - public ActionLink() { - super(getTooltip(), getDisable(), getConfirm(), getPrototyping(), getIcon()); - } - - //TODO this is yet the result of refactoring the logic originating from the wicket viewer - //I'm not happy with this yet: this code decorates 2 UI components at once which is confusing - //also is not generic enough, because wicket still needs to override this in order to decorate - //even another UI component - private <T extends Component> void commonDecorateMenuItem( - final T uiComponent, // UI component #1 - final LinkAndLabel linkAndLabel, - final TranslationService translationService) { - - val actionLinkUiComponent = linkAndLabel.getUiComponent(); // UI component #2 - val actionMeta = linkAndLabel.getManagedAction().getAction(); - - linkAndLabel.getDisableUiModel().ifPresent(disableUiModel->{ - getDisableDecorator().decorate(uiComponent, disableUiModel); - getTooltipDecorator().decorate(uiComponent, - TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, disableUiModel.getReason())); + @Override + public void decorate( + ListItem<? extends Menuable> listItem, + AjaxLink<ManagedObject> actionLink, + Label menuItemLabel, + MenuActionDecorationModel decorationModel) { + Wkt.cssAppend(listItem, decorationModel.featureIdentifier()); + + decorationModel.disabling() + .ifPresentOrElse(disableUiModel->{ + getDisable().decorate(listItem, disableUiModel); + getTooltip().decorate(listItem, + TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, disableUiModel.reason())); + }, ()->{ + decorationModel + .describedAs() + .ifPresent(describedAs-> + getTooltip() + .decorate(listItem, + TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, describedAs))); + + //{CAUSEWAY-1626] confirmation dialog for no-parameter menu actions + if (decorationModel.isImmediateConfirmationRequired()) { + var confirmUiModel = ConfirmDecorationModel.areYouSure(UiPlacementDirection.BOTTOM); + getConfirm().decorate(actionLink, confirmUiModel); + } + + }); + + decorationModel.prototyping().ifPresent(protoDecModel->{ + getPrototyping().decorate(actionLink, protoDecModel); }); - - if (!linkAndLabel.getDisableUiModel().isPresent()) { - - linkAndLabel - .getDescription() - .ifPresent(describedAs-> - getTooltipDecorator() - .decorate(uiComponent, - TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, describedAs))); - - //XXX CAUSEWAY-1626, confirmation dialog for no-parameter menu actions - if (actionMeta.isImmediateConfirmationRequired()) { - - val confirmUiModel = ConfirmDecorationModel.areYouSure(translationService, UiPlacementDirection.BOTTOM); - getConfirmDecorator().decorate(actionLinkUiComponent, confirmUiModel); - - } - - } - - if (actionMeta.isPrototype()) { - getPrototypingDecorator() - .decorate(actionLinkUiComponent, PrototypingDecorationModel.of(linkAndLabel.getManagedAction())); - } - - } - - public void decorateMenuItem( - final Component uiComponent, - final LinkAndLabel linkAndLabel, - final TranslationService translationService) { - - Wkt.cssAppend(uiComponent, linkAndLabel.getFeatureIdentifier()); - - commonDecorateMenuItem(uiComponent, linkAndLabel, translationService); - - linkAndLabel.getAdditionalCssClass() - .ifPresent(cssClass->Wkt.cssAppend(linkAndLabel.getUiComponent(), cssClass)); + + decorationModel.additionalCssClass() + .ifPresent(cssClass->Wkt.cssAppend(actionLink, cssClass)); + + var faLayers = decorationModel.fontAwesomeLayers(); + getIcon().decorate(menuItemLabel, faLayers); + getMissingIcon().decorate(actionLink, faLayers); } } diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java index ba211b4190..aea04b86ed 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java @@ -44,7 +44,6 @@ import org.apache.causeway.viewer.wicket.ui.components.widgets.linkandlabel.Acti import org.apache.causeway.viewer.wicket.ui.util.BootstrapConstants.ButtonSemantics; import lombok.NonNull; -import lombok.val; import lombok.experimental.UtilityClass; @UtilityClass @@ -64,10 +63,11 @@ public final class WktLinks { final LinkAndLabel linkAndLabel, final boolean isForceAlignmentWithBlankIcon) { - val link = linkAndLabel.getUiComponent(); - val action = linkAndLabel.getManagedAction().getAction(); + var link = linkAndLabel.getUiComponent(); + var action = linkAndLabel.getManagedAction().getAction(); - val hasDisabledReason = link instanceof ActionLink && _Strings.isNotEmpty(((ActionLink) link).getReasonDisabledIfAny()); + var hasDisabledReason = link instanceof ActionLink + && _Strings.isNotEmpty(((ActionLink) link).getReasonDisabledIfAny()); WktTooltips.addTooltip(tooltipReceiver, hasDisabledReason ? ((ActionLink) link).getReasonDisabledIfAny() @@ -84,10 +84,8 @@ public final class WktLinks { if (action.getSemantics().isAreYouSure()) { if(action.getParameterCount()==0) { if (!hasDisabledReason) { - val translationService = linkAndLabel.getAction().getMetaModelContext() - .getTranslationService(); - val confirmUiModel = ConfirmDecorationModel - .areYouSure(translationService, UiPlacementDirection.BOTTOM); + var confirmUiModel = ConfirmDecorationModel + .areYouSure(UiPlacementDirection.BOTTOM); WktDecorators.getConfirm().decorate(link, confirmUiModel); } } @@ -105,10 +103,10 @@ public final class WktLinks { .getAdditionalCssClass() .ifPresent(cssClass->Wkt.cssAppend(link, cssClass)); - val viewTitleLabel = Wkt.labelAdd(link, titleId, + var viewTitleLabel = Wkt.labelAdd(link, titleId, linkAndLabel::getFriendlyName); - val faLayers = linkAndLabel.lookupFontAwesomeLayers(isForceAlignmentWithBlankIcon); + var faLayers = linkAndLabel.lookupFontAwesomeLayers(isForceAlignmentWithBlankIcon); WktDecorators.getIcon().decorate(viewTitleLabel, faLayers); WktDecorators.getMissingIcon().decorate(viewTitleLabel, faLayers); @@ -122,7 +120,7 @@ public final class WktLinks { final @NonNull String iconId, final @Nullable Function<T, IModel<String>> iconProvider, final @Nullable BiFunction<T, Label, IModel<String>> cssFactory) { - val t = item.getModelObject(); + var t = item.getModelObject(); // add title and icon to the link diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java index 5cd30e9935..5d84648e9b 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java @@ -73,12 +73,12 @@ public class WktTooltips { } } - val placementDirection = tooltipDecorationModel.getPlacementDirection(); + val placementDirection = tooltipDecorationModel.placementDirection(); - final IModel<String> bodyModel = Model.of(tooltipDecorationModel.getBody()); + final IModel<String> bodyModel = Model.of(tooltipDecorationModel.body()); val tooltipBehavior = tooltipDecorationModel - .getTitle() + .title() .map(title->Model.of(title)) .map(titleModel->createTooltipBehavior(placementDirection, titleModel, bodyModel)) .orElseGet(()->createTooltipBehavior(placementDirection, bodyModel));
