This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v4
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/v4 by this push:
     new e05c34ecb28 CAUSEWAY-3904: adds support for url based icons to select2 
widget
e05c34ecb28 is described below

commit e05c34ecb2818d162d47de57a933161ae06790ab
Author: Andi Huber <[email protected]>
AuthorDate: Fri Sep 19 12:23:55 2025 +0200

    CAUSEWAY-3904: adds support for url based icons to select2 widget
---
 api/applib/src/main/java/module-info.java          |  2 +-
 .../causeway/applib/annotation/ObjectSupport.java  | 22 +++++--
 .../causeway/applib/events/ui/IconUiEvent.java     |  4 +-
 .../services/appfeatui/ApplicationFeatureMenu.java |  2 +-
 .../appfeatui/ApplicationFeatureViewModel.java     |  2 +-
 .../applib/services/render}/ObjectIcon.java        |  2 +-
 .../services/render}/ObjectIconEmbedded.java       |  2 +-
 .../applib/services/render}/ObjectIconFa.java      |  2 +-
 .../services/render}/ObjectIconUrlBased.java       |  2 +-
 .../services/render/ObjectRenderService.java       | 56 ++++++++++++++++
 .../PlaceholderRenderService.java                  |  2 +-
 .../applib/services/title/TitleService.java        |  4 +-
 .../org/apache/causeway/applib/value/Password.java |  4 +-
 .../value/semantics/ValueSemanticsAbstract.java    |  4 +-
 .../causeway/applib/value/Password_Test.java       |  2 +-
 .../metamodel/context/HasMetaModelContext.java     |  8 ++-
 .../core/metamodel/context/MetaModelContext.java   |  4 +-
 .../context/MetaModelContext_usingSpring.java      |  8 ++-
 .../metamodel/facets/FacetFactoryAbstract.java     |  2 +-
 ...mainObjectLayoutAnnotationUsingIconUiEvent.java | 10 +--
 .../metamodel/facets/object/icon/IconFacet.java    |  4 +-
 .../facets/object/icon/ObjectIconService.java      | 13 ++--
 .../object/icon/method/IconFacetViaIconMethod.java |  6 +-
 .../icon/method/IconFacetViaIconNameMethod.java    |  4 +-
 .../ident/IconFacetFromProjectionFacet.java        |  4 +-
 .../inspect/model/MetamodelInspectView.java        |  2 +-
 .../core/metamodel/object/ManagedObject.java       | 10 +--
 .../objectmanager/memento/ObjectMemento.java       | 25 ++------
 .../services/title/TitleServiceDefault.java        |  4 +-
 .../core/metamodel/spec/ObjectSpecification.java   |  2 +-
 .../spec/impl/ObjectSpecificationDefault.java      |  4 +-
 .../valuesemantics/PasswordValueSemantics.java     |  2 +-
 .../object/ident/icon/IconFacetMethodFaTest.java   |  6 +-
 .../ident/icon/IconFacetMethodFactoryTest.java     |  4 +-
 .../object/ident/icon/IconFacetMethodTest.java     |  8 +--
 .../value/BooleanValueSemanticsProviderTest.java   |  2 +-
 .../ValueSemanticsProviderAbstractTestCase.java    |  2 +-
 .../mmtestsupport/MetaModelContext_forTesting.java |  6 +-
 .../core/mmtestsupport/TitleServiceForTesting.java |  2 +-
 .../runtimeservices/src/main/java/module-info.java |  2 +-
 .../CausewayModuleCoreRuntimeServices.java         |  2 +-
 .../icons/ObjectIconServiceDefault.java            | 14 ++--
 .../PlaceholderRenderServiceDefault.java           |  4 +-
 .../testdomain/model/good/ProperFullyAbstract.java |  2 +-
 .../testdomain/model/good/ProperFullyImpl.java     |  2 +-
 .../good/ProperMemberInheritanceAbstract.java      |  2 +-
 .../good/ProperMemberInheritanceInterface.java     |  2 +-
 .../interaction/DomainObjectTesterFactory.java     |  6 +-
 .../DomainModelTest_usingGoodDomain.java           |  6 +-
 .../value/PropertyInteractionProbeImpl.java        |  2 +-
 .../viewer/commons/model/mixin/HasIcon.java        | 16 ++---
 .../resources/DomainObjectResourceServerside.java  |  4 +-
 .../wicket/model/models/BookmarkTreeNode.java      |  6 +-
 .../wicket/model/models/BookmarkableModel.java     |  6 +-
 .../wicket/model/models/ImageResourceCache.java    |  2 +-
 .../viewer/wicket/model/models/UiObjectWkt.java    | 14 ++--
 .../select2/ChoiceProviderTestAbstract.java        |  2 +-
 .../attributes/AttributePanelWithInlinePrompt.java |  2 +-
 .../blobclob/BlobOrClobAttributePanel.java         |  2 +-
 .../choices/ObjectChoicesAttributePanel.java       |  2 +-
 .../attributes/image/ImageAttributePanel.java      |  2 +-
 .../present/ajaxtable/columns/PluralColumn.java    |  2 +-
 .../object/icontitle/ObjectIconAndTitlePanel.java  | 40 ++++++------
 .../icontitle/ObjectIconAndTitlePanelFactory.java  |  6 +-
 .../icontitle/ObjectIconTitleAndCopyLinkPanel.java |  6 +-
 .../ObjectIconTitleAndCopyLinkPanelFactory.java    |  4 +-
 .../objectsimplelink/ObjectLinkSimplePanel.java    |  2 +-
 .../bootstrap/css/bootstrap-overrides-all-v2.css   | 12 ++--
 .../viewer/CausewayModuleViewerWicketViewer.java   |  2 +
 .../services/ImageResourceCacheClassPath.java      |  2 +-
 .../viewer/services/ObjectRenderServiceWicket.java | 75 ++++++++++++++++++++++
 71 files changed, 329 insertions(+), 178 deletions(-)

diff --git a/api/applib/src/main/java/module-info.java 
b/api/applib/src/main/java/module-info.java
index 3fd0454a368..0077e14fcc7 100644
--- a/api/applib/src/main/java/module-info.java
+++ b/api/applib/src/main/java/module-info.java
@@ -89,11 +89,11 @@
     exports org.apache.causeway.applib.services.metamodel;
     exports org.apache.causeway.applib.services.metamodel.objgraph;
     exports org.apache.causeway.applib.services.metrics;
-    exports org.apache.causeway.applib.services.placeholder;
     exports org.apache.causeway.applib.services.publishing.log;
     exports org.apache.causeway.applib.services.publishing.spi;
     exports org.apache.causeway.applib.services.queryresultscache;
     exports org.apache.causeway.applib.services.registry;
+    exports org.apache.causeway.applib.services.render;
     exports org.apache.causeway.applib.services.repository;
     exports org.apache.causeway.applib.services.routing;
     exports org.apache.causeway.applib.services.scratchpad;
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/annotation/ObjectSupport.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/annotation/ObjectSupport.java
index 345ea50ff95..a577dd49ca3 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/annotation/ObjectSupport.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/annotation/ObjectSupport.java
@@ -53,12 +53,24 @@
 
     /**
      * Rendering context for object icons.
-     * An object's icon is either rendered within the object detail page 
header (along its title)
-     * or within a table row.
+     * An object's icon is rendered within the object detail page header along 
its title {@link IconSize#LARGE},
+     * within a table row {@link IconSize#MEDIUM}, as property {@link 
IconSize#MEDIUM}, as tree node {@link IconSize#MEDIUM}
+     * or as choice {@link IconSize#SMALL}.
+     * @since 4.0
      */
-    public enum IconWhere {
-        OBJECT_HEADER,
-        TABLE_ROW //TODO also TREE_NODE and SELECT_DROPDOWN
+    public enum IconSize {
+        /**
+         * as used for the object detail page header (along the object's title)
+         */
+        LARGE,
+        /**
+         * as used for table data, properties and tree nodes
+         */
+        MEDIUM,
+        /**
+         * as used for choice drop downs (single- and multi-choice)
+         */
+        SMALL
     }
 
     public sealed interface IconResource extends Serializable
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/events/ui/IconUiEvent.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/events/ui/IconUiEvent.java
index 5cc0242c6db..1e4d8d762b0 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/events/ui/IconUiEvent.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/events/ui/IconUiEvent.java
@@ -55,11 +55,11 @@ protected IconUiEvent() {
     }
 
     @Getter @Setter @Accessors(fluent = true)
-    private ObjectSupport.IconWhere iconWhere;
+    private ObjectSupport.IconSize iconSize;
 
     /**
      * Icon resource for corresponding domain object,
-     * which subscribers may set, based on {@link #iconWhere()}.
+     * which subscribers may set, based on {@link #iconSize()}.
      */
     @Getter @Setter
     private ObjectSupport.IconResource icon;
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureMenu.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureMenu.java
index 96f3bdc94a3..f7fe9d018d0 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureMenu.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureMenu.java
@@ -65,7 +65,7 @@ public static abstract class ActionDomainEvent
 
     // -- ICON
 
-    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
         return new ObjectSupport.ClassPathIconResource("applicationFeature");
     }
 
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureViewModel.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureViewModel.java
index c36588944cd..ce1845c76c6 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureViewModel.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeatui/ApplicationFeatureViewModel.java
@@ -143,7 +143,7 @@ public ApplicationFeatureViewModel() {
     @ObjectSupport public String title() {
         return getFullyQualifiedName();
     }
-    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
         return new ObjectSupport.ClassPathIconResource("applicationFeature");
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIcon.java
similarity index 96%
rename from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
rename to 
api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIcon.java
index 4bcb890d579..596575608b0 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIcon.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.metamodel.facets.object.icon;
+package org.apache.causeway.applib.services.render;
 
 import java.io.Serializable;
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconEmbedded.java
similarity index 95%
rename from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
rename to 
api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconEmbedded.java
index 70cc2c10f41..af82d73c38b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconEmbedded.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconEmbedded.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.metamodel.facets.object.icon;
+package org.apache.causeway.applib.services.render;
 
 import org.apache.causeway.applib.services.title.TitleService;
 import org.apache.causeway.commons.net.DataUri;
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconFa.java
similarity index 95%
rename from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
rename to 
api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconFa.java
index 64154b5682c..911c753be01 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconFa.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconFa.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.metamodel.facets.object.icon;
+package org.apache.causeway.applib.services.render;
 
 import java.nio.charset.StandardCharsets;
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconUrlBased.java
similarity index 98%
rename from 
core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
rename to 
api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconUrlBased.java
index 74c3eb6324c..08c90f0acb8 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconUrlBased.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectIconUrlBased.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.metamodel.facets.object.icon;
+package org.apache.causeway.applib.services.render;
 
 import java.io.InputStream;
 import java.net.URL;
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectRenderService.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectRenderService.java
new file mode 100644
index 00000000000..278680316d4
--- /dev/null
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/ObjectRenderService.java
@@ -0,0 +1,56 @@
+/*
+ *  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.applib.services.render;
+
+import org.jspecify.annotations.Nullable;
+
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
+
+/**
+ * <h1>Experimental</h1>
+ * Service that renders various aspects of a domain object, enum or value, as 
presented with the UI.
+ * <ul>
+ * <li>icon</li>
+ * <li>title</li>
+ * <li>description</li>
+ * </ul>
+ *
+ * @since 4.0 {@index}
+ */
+public interface ObjectRenderService {
+
+    String iconToHtml(@Nullable ObjectIcon objectIcon, IconSize iconSize);
+
+    static ObjectRenderService fallback() {
+        return (@Nullable ObjectIcon objectIcon, IconSize iconSize) -> {
+            //if(true) return "<i class=\"%s\"></i>".formatted("fa-solid 
fa-thumbs-up");
+
+            //TODO not supported yet as requires resource caching from wicket
+//                if(objectIcon instanceof ObjectIconUrlBased urlBased)
+//                    return "<img src=\"" + urlBased.url().toExternalForm() + 
"\"/>";
+            if(objectIcon instanceof ObjectIconEmbedded embedded)
+                return "<img src=\"" + embedded.dataUri().toExternalForm() + 
"\"/>";
+            if(objectIcon instanceof ObjectIconFa fa)
+                return fa.fontAwesomeLayers().toHtml();
+
+            return null;
+        };
+    }
+
+}
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/placeholder/PlaceholderRenderService.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/PlaceholderRenderService.java
similarity index 98%
rename from 
api/applib/src/main/java/org/apache/causeway/applib/services/placeholder/PlaceholderRenderService.java
rename to 
api/applib/src/main/java/org/apache/causeway/applib/services/render/PlaceholderRenderService.java
index bd61fd9ae4d..93e7a1cdf71 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/placeholder/PlaceholderRenderService.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/render/PlaceholderRenderService.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.applib.services.placeholder;
+package org.apache.causeway.applib.services.render;
 
 import java.util.Map;
 
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/title/TitleService.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/title/TitleService.java
index 1080d070e33..bcf5f466e17 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/title/TitleService.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/title/TitleService.java
@@ -19,7 +19,7 @@
 package org.apache.causeway.applib.services.title;
 
 import org.apache.causeway.applib.annotation.ObjectSupport.IconResource;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 
 /**
  * Provides methods to programmatically obtain the title and icon of a domain
@@ -39,6 +39,6 @@ public interface TitleService {
      * Returns the icon of the object (as rendered in the UI by the
      * framework's viewers).
      */
-    IconResource iconOf(Object domainObject, IconWhere iconWhere);
+    IconResource iconOf(Object domainObject, IconSize iconSize);
 
 }
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/value/Password.java 
b/api/applib/src/main/java/org/apache/causeway/applib/value/Password.java
index 26f79e2ef62..a54ab631329 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/value/Password.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/value/Password.java
@@ -27,8 +27,8 @@
 
 import org.apache.causeway.applib.CausewayModuleApplib;
 import org.apache.causeway.applib.annotation.Value;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 
 /**
  * Represents a password that will not displayed to the UI but can be 
persisted.
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/ValueSemanticsAbstract.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/ValueSemanticsAbstract.java
index 79d584225db..40e599550b0 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/ValueSemanticsAbstract.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/value/semantics/ValueSemanticsAbstract.java
@@ -46,8 +46,8 @@
 import org.apache.causeway.applib.services.i18n.TranslationContext;
 import org.apache.causeway.applib.services.i18n.TranslationService;
 import org.apache.causeway.applib.services.iactnlayer.InteractionContext;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.applib.util.schema.CommonDtoUtils;
 import 
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.EditingFormatDirection;
 import 
org.apache.causeway.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
diff --git 
a/api/applib/src/test/java/org/apache/causeway/applib/value/Password_Test.java 
b/api/applib/src/test/java/org/apache/causeway/applib/value/Password_Test.java
index aba73f388bb..9cd3bc20b9e 100644
--- 
a/api/applib/src/test/java/org/apache/causeway/applib/value/Password_Test.java
+++ 
b/api/applib/src/test/java/org/apache/causeway/applib/value/Password_Test.java
@@ -25,7 +25,7 @@
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 
 class Password_Test {
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/HasMetaModelContext.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/HasMetaModelContext.java
index d42f0b10084..94f3b0a3332 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/HasMetaModelContext.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/HasMetaModelContext.java
@@ -26,8 +26,9 @@
 import org.apache.causeway.applib.services.inject.ServiceInjector;
 import org.apache.causeway.applib.services.menu.MenuBarsService;
 import org.apache.causeway.applib.services.message.MessageService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
 import org.apache.causeway.applib.services.registry.ServiceRegistry;
+import org.apache.causeway.applib.services.render.ObjectRenderService;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
 import org.apache.causeway.applib.services.title.TitleService;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
@@ -150,6 +151,11 @@ default WrapperFactory getWrapperFactory() {
         return getMetaModelContext().getWrapperFactory();
     }
 
+    @Override
+    default ObjectRenderService getObjectRenderService() {
+        return getMetaModelContext().getObjectRenderService();
+    }
+
     @Override
     default PlaceholderRenderService getPlaceholderRenderService() {
         return getMetaModelContext().getPlaceholderRenderService();
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext.java
index 579a16452a2..94321098b32 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext.java
@@ -30,8 +30,9 @@
 import org.apache.causeway.applib.services.inject.ServiceInjector;
 import org.apache.causeway.applib.services.menu.MenuBarsService;
 import org.apache.causeway.applib.services.message.MessageService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
 import org.apache.causeway.applib.services.registry.ServiceRegistry;
+import org.apache.causeway.applib.services.render.ObjectRenderService;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
 import org.apache.causeway.applib.services.title.TitleService;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
@@ -102,6 +103,7 @@ default MetaModelContext mmc() {
     RepositoryService getRepositoryService();
     ManagedObject getHomePageAdapter();
     TransactionService getTransactionService();
+    ObjectRenderService getObjectRenderService();
     ObjectIconService getObjectIconService();
     MessageService getMessageService();
     ObjectManager getObjectManager();
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext_usingSpring.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext_usingSpring.java
index f149b0769b4..7f34cdf498c 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext_usingSpring.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/context/MetaModelContext_usingSpring.java
@@ -31,8 +31,9 @@
 import org.apache.causeway.applib.services.inject.ServiceInjector;
 import org.apache.causeway.applib.services.menu.MenuBarsService;
 import org.apache.causeway.applib.services.message.MessageService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
 import org.apache.causeway.applib.services.registry.ServiceRegistry;
+import org.apache.causeway.applib.services.render.ObjectRenderService;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
 import org.apache.causeway.applib.services.title.TitleService;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
@@ -115,6 +116,11 @@ void onDestroy() {
     private final ObjectIconService objectIconService =
     getSingletonElseFail(ObjectIconService.class);
 
+    @Getter(lazy=true)
+    private final ObjectRenderService objectRenderService =
+            getDefault(ObjectRenderService.class)
+            .orElseGet(ObjectRenderService::fallback);
+
     @Getter(lazy=true)
     private final PlaceholderRenderService placeholderRenderService =
             getDefault(PlaceholderRenderService.class)
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/FacetFactoryAbstract.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/FacetFactoryAbstract.java
index de808242092..a255b8b2021 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/FacetFactoryAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/FacetFactoryAbstract.java
@@ -88,6 +88,6 @@ public <F extends Facet> Optional<F> addFacetIfPresent(final 
@Nullable Optional<
 
     protected static final Class<?>[] NO_ARG = new Class<?>[0];
     protected static final Class<?>[] STRING_ARG = new Class<?>[] 
{String.class};
-    protected static final Class<?>[] ICON_WHERE_ARG = new Class<?>[] 
{ObjectSupport.IconWhere.class};
+    protected static final Class<?>[] ICON_WHERE_ARG = new Class<?>[] 
{ObjectSupport.IconSize.class};
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
index e2dc74d72cb..722c57308db 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobjectlayout/IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent.java
@@ -67,11 +67,11 @@ public static 
Optional<IconFacetViaDomainObjectLayoutAnnotationUsingIconUiEvent>
 
 
     @Override
-    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, ObjectSupport.IconWhere iconWhere) {
+    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, ObjectSupport.IconSize iconSize) {
 
         if(ManagedObjects.isNullOrUnspecifiedOrEmpty(domainObject)) return 
Optional.empty();
 
-        final IconUiEvent<Object> iconUiEvent = newIconUiEvent(domainObject, 
iconWhere);
+        final IconUiEvent<Object> iconUiEvent = newIconUiEvent(domainObject, 
iconSize);
 
         metamodelEventService.fireIconUiEvent(iconUiEvent);
 
@@ -81,7 +81,7 @@ public Optional<ObjectSupport.IconResource> 
icon(ManagedObject domainObject, Obj
             // ie no subscribers out there...
 
             icon = underlyingIconFacet()
-                
.flatMap(underlyingIconFacet->underlyingIconFacet.icon(domainObject, iconWhere))
+                
.flatMap(underlyingIconFacet->underlyingIconFacet.icon(domainObject, iconSize))
                 .orElse(null);
         }
 
@@ -95,10 +95,10 @@ public void visitAttributes(final BiConsumer<String, 
Object> visitor) {
         visitor.accept("iconUiEventClass", iconUiEventClass);
     }
 
-    private IconUiEvent<Object> newIconUiEvent(final ManagedObject 
owningAdapter, ObjectSupport.IconWhere iconWhere) {
+    private IconUiEvent<Object> newIconUiEvent(final ManagedObject 
owningAdapter, ObjectSupport.IconSize iconSize) {
         var iconUiEvent = 
EventObjectBase.getInstanceWithSourceSupplier(iconUiEventClass, 
owningAdapter::getPojo)
             .orElseThrow();
-        return iconUiEvent.iconWhere(iconWhere);
+        return iconUiEvent.iconSize(iconSize);
     }
 
     private Optional<IconFacet> underlyingIconFacet() {
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
index f04b8b8b727..8c3eaaced20 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/IconFacet.java
@@ -21,7 +21,7 @@
 import java.util.Optional;
 
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.core.metamodel.facetapi.Facet;
 import org.apache.causeway.core.metamodel.facets.object.title.TitleFacet;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
@@ -44,6 +44,6 @@
  */
 public interface IconFacet extends Facet {
 
-    Optional<ObjectSupport.IconResource> icon(ManagedObject object, IconWhere 
iconWhere);
+    Optional<ObjectSupport.IconResource> icon(ManagedObject object, IconSize 
iconSize);
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
index 1c1a00f95a3..a1b1e173180 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIconService.java
@@ -19,7 +19,8 @@
 package org.apache.causeway.core.metamodel.facets.object.icon;
 
 import org.apache.causeway.applib.annotation.ObjectSupport.IconResource;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
+import org.apache.causeway.applib.services.render.ObjectIcon;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 
@@ -27,17 +28,17 @@
  * Resolves instances of {@link IconResource} to instances of {@link 
ObjectIcon}.
  *
  * <p>Clients should not use this service directly. Either use
- * {@link ManagedObject#getIcon(IconWhere)} or
- * {@link 
ObjectSpecification#getIcon(org.apache.causeway.core.metamodel.object.ManagedObject,
 IconWhere)}.
+ * {@link ManagedObject#getIcon(IconSize)} or
+ * {@link 
ObjectSpecification#getIcon(org.apache.causeway.core.metamodel.object.ManagedObject,
 IconSize)}.
  *
  * @apiNote internal service, used by the metamodel
  *
- * @see ManagedObject#getIcon(IconWhere)
- * @see 
ObjectSpecification#getIcon(org.apache.causeway.core.metamodel.object.ManagedObject,
 IconWhere)
+ * @see ManagedObject#getIcon(IconSize)
+ * @see 
ObjectSpecification#getIcon(org.apache.causeway.core.metamodel.object.ManagedObject,
 IconSize)
  * @since 2.0 revised for 4.0
  */
 public interface ObjectIconService {
 
-    ObjectIcon getObjectIcon(ManagedObject managedObject, IconWhere iconWhere);
+    ObjectIcon getObjectIcon(ManagedObject managedObject, IconSize iconSize);
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java
index 7060dea4071..f10ed5cb8a9 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java
@@ -26,7 +26,7 @@
 import org.springframework.util.ClassUtils;
 
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import 
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
 import org.apache.causeway.core.metamodel.facetapi.Facet;
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
@@ -56,8 +56,8 @@ public static Optional<IconFacet> create(
     @Override public ImperativeAspect getImperativeAspect() { return 
imperativeAspect; }
 
     @Override
-    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, IconWhere iconWhere) {
-        return Optional.ofNullable(imperativeAspect.eval(domainObject, 
(ObjectSupport.IconResource)null, iconWhere));
+    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, IconSize iconSize) {
+        return Optional.ofNullable(imperativeAspect.eval(domainObject, 
(ObjectSupport.IconResource)null, iconSize));
     }
 
     @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
index cf9f31d2d5f..d766fd598bb 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java
@@ -26,7 +26,7 @@
 import org.springframework.util.ClassUtils;
 
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.commons.internal.base._Strings;
 import 
org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod;
 import org.apache.causeway.core.metamodel.facetapi.Facet;
@@ -57,7 +57,7 @@ public static Optional<IconFacet> create(
     @Override public ImperativeAspect getImperativeAspect() { return 
imperativeAspect; }
 
     @Override
-    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, IconWhere iconWhere) {
+    public Optional<ObjectSupport.IconResource> icon(ManagedObject 
domainObject, IconSize iconSize) {
         return Optional.of(new ObjectSupport.ClassPathIconResource(
             _Strings.nullToEmpty(imperativeAspect.eval(domainObject, 
(String)null))));
     }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
index 0ff1196bb5d..a3378bb7a06 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/projection/ident/IconFacetFromProjectionFacet.java
@@ -42,9 +42,9 @@ public record IconFacetFromProjectionFacet(
     @Override public Precedence getPrecedence() { return Precedence.DEFAULT; }
 
     @Override
-    public Optional<ObjectSupport.IconResource> icon(final ManagedObject 
targetAdapter, final ObjectSupport.IconWhere iconWhere) {
+    public Optional<ObjectSupport.IconResource> icon(final ManagedObject 
targetAdapter, final ObjectSupport.IconSize iconSize) {
         var projectedAdapter = projectionFacet.projected(targetAdapter);
-        return projectedAdapter.objSpec().getIcon(projectedAdapter, iconWhere);
+        return projectedAdapter.objSpec().getIcon(projectedAdapter, iconSize);
     }
 
     @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/inspect/model/MetamodelInspectView.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/inspect/model/MetamodelInspectView.java
index a6ebcf49ac5..2121d9e4bdf 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/inspect/model/MetamodelInspectView.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/inspect/model/MetamodelInspectView.java
@@ -75,7 +75,7 @@ public String title() {
     }
 
     @ObjectSupport
-    public ObjectSupport.IconResource icon(final ObjectSupport.IconWhere 
iconWhere) {
+    public ObjectSupport.IconResource icon(final ObjectSupport.IconSize 
iconSize) {
         return new ObjectSupport.ClassPathIconResource(
             activeNode().getClass().getSimpleName()
             + _Strings.nonEmpty(activeNode().iconName())
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
index 54f6c84d24a..117f3f9d28b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/ManagedObject.java
@@ -24,15 +24,15 @@
 import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
+import org.apache.causeway.applib.services.render.ObjectIcon;
 import org.apache.causeway.applib.services.repository.EntityState;
 import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.functional.Either;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import org.apache.causeway.core.metamodel.spec.HasObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
@@ -384,10 +384,10 @@ default EntityState getEntityState() {
     /**
      * Domain Objects may either have an icon corresponding to an icon 
resource,
      * or they use a font awesome icon.
-     * @param iconWhere
+     * @param iconSize
      */
-    default ObjectIcon getIcon(IconWhere iconWhere) {
-        return getObjectIconService().getObjectIcon(this, iconWhere);
+    default ObjectIcon getIcon(IconSize iconSize) {
+        return getObjectIconService().getObjectIcon(this, iconSize);
     }
 
     default Either<ManagedObject, ManagedObject> 
asEitherWithOrWithoutMemoizedBookmark() {
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/objectmanager/memento/ObjectMemento.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/objectmanager/memento/ObjectMemento.java
index d53678f7578..282a099294b 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/objectmanager/memento/ObjectMemento.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/objectmanager/memento/ObjectMemento.java
@@ -27,18 +27,15 @@
 
 import org.springframework.util.StringUtils;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.id.LogicalType;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.i18n.TranslationContext;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.collections._Lists;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconFa;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.object.MmAssertionUtils;
@@ -93,7 +90,7 @@ static Optional<ObjectMemento> singular(
                 adapter.logicalType(),
                 MmHintUtils.bookmarkElseFail(adapter),
                 
adapter.getTranslationService().translate(TranslationContext.empty(), 
MmTitleUtils.titleOf(adapter)),
-                iconToHtml(adapter.getIcon(IconWhere.TABLE_ROW))));
+                
adapter.getObjectRenderService().iconToHtml(adapter.getIcon(IconSize.SMALL), 
IconSize.SMALL)));
     }
     /**
      * returns null for null
@@ -124,20 +121,6 @@ static ObjectMemento packed(
 
     // -- UTILITY
 
-    private static String iconToHtml(@Nullable ObjectIcon objectIcon) {
-        //if(true) return "<i class=\"%s\"></i>".formatted("fa-solid 
fa-thumbs-up");
-
-        //TODO not supported yet as requires resource caching from wicket
-//        if(objectIcon instanceof ObjectIconUrlBased urlBased)
-//            return "<img src=\"" + urlBased.url().toExternalForm() + "\"/>";
-        if(objectIcon instanceof ObjectIconEmbedded embedded)
-            return "<img src=\"" + embedded.dataUri().toExternalForm() + 
"\"/>";
-        if(objectIcon instanceof ObjectIconFa fa)
-            return fa.fontAwesomeLayers().toHtml();
-
-        return null;
-    }
-
     static ObjectMemento fromDto(final ObjectDisplayDto dto) {
         var bookmark = Bookmark.parse(dto.bookmark()).orElseThrow();
         var logicalType = new LogicalType(bookmark.logicalTypeName(), 
dto.correspondingClass());
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
index cf853b11228..2a55983c7fb 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitleServiceDefault.java
@@ -62,13 +62,13 @@ public String titleOf(final Object domainObject) {
     }
 
     @Override
-    public ObjectSupport.IconResource iconOf(final Object domainObject, final 
ObjectSupport.IconWhere iconWhere) {
+    public ObjectSupport.IconResource iconOf(final Object domainObject, final 
ObjectSupport.IconSize iconSize) {
         var pojo = unwrapped(domainObject);
         var objectAdapter = objectManager.adapt(pojo);
 
         return ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)
             ? null
-            : objectAdapter.objSpec().getIcon(objectAdapter, iconWhere)
+            : objectAdapter.objSpec().getIcon(objectAdapter, iconSize)
                 .orElse(null);
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
index 2e0f4b4e699..d2ecdd8ca1a 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java
@@ -250,7 +250,7 @@ default Optional<MixedInAction> lookupMixedInAction(final 
ObjectSpecification mi
      * @see ObjectIconService
      * @since 4.0
      */
-    Optional<ObjectSupport.IconResource> getIcon(ManagedObject object, 
ObjectSupport.IconWhere iconWhere);
+    Optional<ObjectSupport.IconResource> getIcon(ManagedObject object, 
ObjectSupport.IconSize iconSize);
 
     /**
      * Returns this object's navigable parent, if any.
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
index 2c8abd37e85..d54315aa954 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java
@@ -803,12 +803,12 @@ public Can<LogicalType> getAliases() {
     // -- ICON
 
     @Override
-    public Optional<ObjectSupport.IconResource> getIcon(final ManagedObject 
domainObject, ObjectSupport.IconWhere iconWhere) {
+    public Optional<ObjectSupport.IconResource> getIcon(final ManagedObject 
domainObject, ObjectSupport.IconSize iconSize) {
         if(ManagedObjects.isSpecified(domainObject)) {
             _Assert.assertEquals(domainObject.objSpec(), this);
         }
         return Optional.ofNullable(iconFacet)
-            .flatMap(facet->facet.icon(domainObject, iconWhere))
+            .flatMap(facet->facet.icon(domainObject, iconSize))
             .or(()->faLayers(domainObject)
                 .map(ObjectSupport.FontAwesomeIconResource::new));
     }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/PasswordValueSemantics.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/PasswordValueSemantics.java
index 643efb75d25..406c24927ab 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/PasswordValueSemantics.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/PasswordValueSemantics.java
@@ -24,7 +24,7 @@
 import org.springframework.stereotype.Component;
 
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.applib.value.Password;
 import org.apache.causeway.applib.value.semantics.Parser;
 import org.apache.causeway.applib.value.semantics.Renderer;
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFaTest.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFaTest.java
index cf730cde426..0cae0fce85d 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFaTest.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFaTest.java
@@ -29,7 +29,7 @@
 import org.apache.causeway.applib.annotation.DomainObject;
 import org.apache.causeway.applib.annotation.Introspection;
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.core.metamodel.facets.FacetFactoryTestAbstract;
 import org.apache.causeway.core.metamodel.facets.object.icon.IconFacet;
@@ -43,7 +43,7 @@ class IconFacetMethodFaTest
 
     @DomainObject(introspection = Introspection.ENCAPSULATION_ENABLED)
     static class DomainObjectWithFontAwesomeIconViaMethod {
-        @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+        @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
             return new 
ObjectSupport.FontAwesomeIconResource(FONTAWESOME_LAYERS_SAMPLE);
         }
     }
@@ -74,7 +74,7 @@ void fontAwesomeLayersViaIconMethod() {
             assertTrue(iconFacet instanceof IconFacetViaIconMethod);
             var imperativeFacet = (IconFacetViaIconMethod)iconFacet;
 
-            var actual = imperativeFacet.icon(domainObject, 
IconWhere.OBJECT_HEADER)
+            var actual = imperativeFacet.icon(domainObject, IconSize.LARGE)
                 
.filter(ObjectSupport.FontAwesomeIconResource.class::isInstance)
                 .map(ObjectSupport.FontAwesomeIconResource.class::cast)
                 .map(ObjectSupport.FontAwesomeIconResource::faLayers)
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFactoryTest.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFactoryTest.java
index b80dc103263..31c2cd013e9 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFactoryTest.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodFactoryTest.java
@@ -31,11 +31,11 @@ class IconFacetMethodFactoryTest
     @Test
     void iconNameMethodPickedUpOnClassAndMethodRemoved() {
         class Customer {
-            @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+            @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
                 return null;
             }
         }
-        assertPicksUp(1, facetFactory, Customer.class, 
ObjectSupportMethod.ICON, IconFacet.class, ObjectSupport.IconWhere.class);
+        assertPicksUp(1, facetFactory, Customer.class, 
ObjectSupportMethod.ICON, IconFacet.class, ObjectSupport.IconSize.class);
     }
 
 }
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
index f4b7124f21c..a94a99b154a 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/ident/icon/IconFacetMethodTest.java
@@ -28,7 +28,7 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.commons.internal.reflection._GenericResolver;
 import org.apache.causeway.core.metamodel.facetapi.FacetHolder;
 import org.apache.causeway.core.metamodel.facets.Mocking;
@@ -44,7 +44,7 @@ class IconFacetMethodTest {
     private DomainObjectWithProblemInIconNameMethod pojo;
 
     public static class DomainObjectWithProblemInIconNameMethod {
-        @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+        @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
             throw new NullPointerException("for testing purposes");
         }
     }
@@ -54,7 +54,7 @@ public void setUp() throws Exception {
 
         pojo = new DomainObjectWithProblemInIconNameMethod();
         var iconMethod = _GenericResolver.testing
-                .resolveMethod(DomainObjectWithProblemInIconNameMethod.class, 
"icon", ObjectSupport.IconWhere.class);
+                .resolveMethod(DomainObjectWithProblemInIconNameMethod.class, 
"icon", ObjectSupport.IconSize.class);
 
         facet = (IconFacetViaIconMethod) IconFacetViaIconMethod
                 .create(iconMethod, Mockito.mock(FacetHolder.class))
@@ -70,7 +70,7 @@ public void tearDown() throws Exception {
 
     @Test
     void iconIsNull() {
-        var icon = facet.icon(mockOwningAdapter, 
IconWhere.OBJECT_HEADER).orElse(null);
+        var icon = facet.icon(mockOwningAdapter, IconSize.LARGE).orElse(null);
         assertThat(icon, is(nullValue()));
     }
 
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
index dcac1804b82..d603e3c101f 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
@@ -25,7 +25,7 @@
 import static org.junit.jupiter.api.Assertions.fail;
 
 import 
org.apache.causeway.applib.exceptions.recoverable.TextEntryParseException;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.core.metamodel.valuesemantics.BooleanValueSemantics;
 
 class BooleanValueSemanticsProviderTest
diff --git 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
index e6203ebfbcf..864dcd8cbe2 100644
--- 
a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
+++ 
b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
@@ -35,7 +35,7 @@
 import org.springframework.boot.test.util.TestPropertyValues;
 
 import org.apache.causeway.applib.services.iactnlayer.InteractionService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.applib.value.Blob;
 import org.apache.causeway.applib.value.Clob;
 import org.apache.causeway.applib.value.semantics.Parser;
diff --git 
a/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/MetaModelContext_forTesting.java
 
b/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/MetaModelContext_forTesting.java
index b170e7e1d3f..36a3f262f7c 100644
--- 
a/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/MetaModelContext_forTesting.java
+++ 
b/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/MetaModelContext_forTesting.java
@@ -47,8 +47,9 @@
 import org.apache.causeway.applib.services.layout.LayoutService;
 import org.apache.causeway.applib.services.menu.MenuBarsService;
 import org.apache.causeway.applib.services.message.MessageService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
 import org.apache.causeway.applib.services.registry.ServiceRegistry;
+import org.apache.causeway.applib.services.render.ObjectRenderService;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
 import org.apache.causeway.applib.services.repository.RepositoryService;
 import org.apache.causeway.applib.services.title.TitleService;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
@@ -227,6 +228,9 @@ public CausewayConfiguration getConfiguration() {
     @Builder.Default @Getter
     private PlaceholderRenderService placeholderRenderService = 
PlaceholderRenderService.fallback();
 
+    @Builder.Default @Getter
+    private ObjectRenderService objectRenderService = 
ObjectRenderService.fallback();
+
     @Singular @Getter
     private List<Object> singletons;
 
diff --git 
a/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/TitleServiceForTesting.java
 
b/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/TitleServiceForTesting.java
index 528e8b1a29c..1efb9d87d86 100644
--- 
a/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/TitleServiceForTesting.java
+++ 
b/core/mmtestsupport/src/main/java/org/apache/causeway/core/mmtestsupport/TitleServiceForTesting.java
@@ -31,7 +31,7 @@ public String titleOf(final Object domainObject) {
     }
 
     @Override
-    public ObjectSupport.IconResource iconOf(final Object domainObject, final 
ObjectSupport.IconWhere iconWhere) {
+    public ObjectSupport.IconResource iconOf(final Object domainObject, final 
ObjectSupport.IconSize iconSize) {
         return domainObject!=null ? new ClassPathIconResource("") : null;
     }
 
diff --git a/core/runtimeservices/src/main/java/module-info.java 
b/core/runtimeservices/src/main/java/module-info.java
index 1d7f6bbef38..de4ab855e19 100644
--- a/core/runtimeservices/src/main/java/module-info.java
+++ b/core/runtimeservices/src/main/java/module-info.java
@@ -32,7 +32,7 @@
     exports org.apache.causeway.core.runtimeservices.locale;
     exports org.apache.causeway.core.runtimeservices.menubars.bootstrap;
     exports org.apache.causeway.core.runtimeservices.message;
-    exports org.apache.causeway.core.runtimeservices.placeholder;
+    exports org.apache.causeway.core.runtimeservices.render;
     exports org.apache.causeway.core.runtimeservices.publish;
     exports org.apache.causeway.core.runtimeservices.recognizer;
     exports org.apache.causeway.core.runtimeservices.recognizer.dae;
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
index fc5ab2910ea..513e4dcf80a 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/CausewayModuleCoreRuntimeServices.java
@@ -46,7 +46,6 @@
 import 
org.apache.causeway.core.runtimeservices.menubars.bootstrap.MenuBarsMarshallerServiceBootstrap;
 import 
org.apache.causeway.core.runtimeservices.menubars.bootstrap.MenuBarsServiceBootstrap;
 import org.apache.causeway.core.runtimeservices.message.MessageServiceDefault;
-import 
org.apache.causeway.core.runtimeservices.placeholder.PlaceholderRenderServiceDefault;
 import 
org.apache.causeway.core.runtimeservices.publish.CommandPublisherDefault;
 import 
org.apache.causeway.core.runtimeservices.publish.EntityChangesPublisherDefault;
 import 
org.apache.causeway.core.runtimeservices.publish.EntityPropertyChangePublisherDefault;
@@ -55,6 +54,7 @@
 import 
org.apache.causeway.core.runtimeservices.publish.ObjectLifecyclePublisherDefault;
 import 
org.apache.causeway.core.runtimeservices.recognizer.ExceptionRecognizerServiceDefault;
 import 
org.apache.causeway.core.runtimeservices.recognizer.dae.ExceptionRecognizerForDataAccessException;
+import 
org.apache.causeway.core.runtimeservices.render.PlaceholderRenderServiceDefault;
 import org.apache.causeway.core.runtimeservices.routing.RoutingServiceDefault;
 import org.apache.causeway.core.runtimeservices.scratchpad.ScratchpadDefault;
 import 
org.apache.causeway.core.runtimeservices.serializing.SerializingAdapterDefault;
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
index 8bf4b559a12..104ee92a773 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/icons/ObjectIconServiceDefault.java
@@ -38,7 +38,11 @@
 import org.apache.causeway.applib.annotation.ObjectSupport;
 import 
org.apache.causeway.applib.annotation.ObjectSupport.EmbeddedIconResource;
 import 
org.apache.causeway.applib.annotation.ObjectSupport.FontAwesomeIconResource;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
+import org.apache.causeway.applib.services.render.ObjectIcon;
+import org.apache.causeway.applib.services.render.ObjectIconEmbedded;
+import org.apache.causeway.applib.services.render.ObjectIconFa;
+import org.apache.causeway.applib.services.render.ObjectIconUrlBased;
 import 
org.apache.causeway.applib.annotation.ObjectSupport.ClassPathIconResource;
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
 import org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
@@ -47,11 +51,7 @@
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.commons.internal.resources._Resources;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconFa;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconService;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
@@ -87,11 +87,11 @@ public ObjectIconServiceDefault(ResourceLoader 
resourceLoader) {
     }
 
     @Override
-    public ObjectIcon getObjectIcon(ManagedObject managedObject, IconWhere 
iconWhere) {
+    public ObjectIcon getObjectIcon(ManagedObject managedObject, IconSize 
iconSize) {
 
         var spec = managedObject.objSpec();
 
-        return spec.getIcon(managedObject, iconWhere)
+        return spec.getIcon(managedObject, iconSize)
             .map(iconResource->{
                 if(iconResource instanceof ObjectSupport.EmbeddedIconResource 
embedded)
                     return embedded(spec, embedded);
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/render/PlaceholderRenderServiceDefault.java
similarity index 95%
rename from 
core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
rename to 
core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/render/PlaceholderRenderServiceDefault.java
index ab6c639e6ef..9f0b2bf6ef9 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/render/PlaceholderRenderServiceDefault.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.causeway.core.runtimeservices.placeholder;
+package org.apache.causeway.core.runtimeservices.render;
 
 import java.util.Map;
 import java.util.Optional;
@@ -32,7 +32,7 @@
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
 import org.apache.causeway.applib.services.i18n.TranslationContext;
 import org.apache.causeway.applib.services.i18n.TranslationService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService;
+import org.apache.causeway.applib.services.render.PlaceholderRenderService;
 import org.apache.causeway.commons.internal.html._BootstrapBadge;
 import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyAbstract.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyAbstract.java
index 1a40784047f..ffa01f4f9c1 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyAbstract.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyAbstract.java
@@ -31,7 +31,7 @@
 abstract class ProperFullyAbstract {
 
     @ObjectSupport public abstract String title();
-    @ObjectSupport public abstract ObjectSupport.IconResource 
icon(ObjectSupport.IconWhere iconWhere);
+    @ObjectSupport public abstract ObjectSupport.IconResource 
icon(ObjectSupport.IconSize iconSize);
     @ObjectSupport public abstract String cssClass();
     @ObjectSupport public abstract String layout();
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyImpl.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyImpl.java
index d5de33dce25..05ccaac04f1 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyImpl.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperFullyImpl.java
@@ -34,7 +34,7 @@ public String title() {
     }
 
     @Override
-    public ObjectSupport.IconResource icon(final ObjectSupport.IconWhere 
iconWhere) {
+    public ObjectSupport.IconResource icon(final ObjectSupport.IconSize 
iconSize) {
         return new ObjectSupport.ClassPathIconResource("icon");
     }
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceAbstract.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceAbstract.java
index f7fbb3d86dd..e40c4d894c4 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceAbstract.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceAbstract.java
@@ -37,7 +37,7 @@ abstract class ProperMemberInheritanceAbstract {
         return "inherited title";
     }
 
-    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+    @ObjectSupport public ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
         return new ObjectSupport.ClassPathIconResource("inherited icon");
     }
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceInterface.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceInterface.java
index d70b7aca363..5fec807d6b9 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceInterface.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/model/good/ProperMemberInheritanceInterface.java
@@ -35,7 +35,7 @@ default String title() {
         return "inherited title";
     }
 
-    @ObjectSupport default ObjectSupport.IconResource icon(final 
ObjectSupport.IconWhere iconWhere) {
+    @ObjectSupport default ObjectSupport.IconResource icon(final 
ObjectSupport.IconSize iconSize) {
         return new ObjectSupport.ClassPathIconResource("inherited icon");
     }
 
diff --git 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
index d9e947164aa..51557c96a23 100644
--- 
a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
+++ 
b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java
@@ -41,7 +41,7 @@
 
 import org.apache.causeway.applib.Identifier;
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.annotation.Where;
 import 
org.apache.causeway.applib.exceptions.unrecoverable.DomainModelException;
 import org.apache.causeway.applib.id.LogicalType;
@@ -229,10 +229,10 @@ public void assertTitle(final @Nullable String 
expectedResult) {
         public void assertIcon(final @Nullable String expectedResult) {
             var expectedIcon = new 
ObjectSupport.ClassPathIconResource(expectedResult);
             assertEquals(expectedIcon,
-                    
super.objectSpecification.getTitleService().iconOf(vm.getPojo(), 
IconWhere.OBJECT_HEADER));
+                    
super.objectSpecification.getTitleService().iconOf(vm.getPojo(), 
IconSize.LARGE));
             assertEquals(expectedIcon,
                     super.objectSpecification.lookupFacet(IconFacet.class)
-                    .flatMap(iconFacet->iconFacet.icon(vm, 
IconWhere.OBJECT_HEADER))
+                    .flatMap(iconFacet->iconFacet.icon(vm, IconSize.LARGE))
                     .orElse(null));
         }
 
diff --git 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index 2e1d5d05516..751096377d9 100644
--- 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -45,7 +45,7 @@
 import org.apache.causeway.applib.annotation.Introspection.EncapsulationPolicy;
 import 
org.apache.causeway.applib.annotation.Introspection.MemberAnnotationPolicy;
 import org.apache.causeway.applib.annotation.ObjectSupport;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.id.LogicalType;
 import org.apache.causeway.applib.services.jaxb.JaxbService;
 import org.apache.causeway.applib.services.metamodel.BeanSort;
@@ -296,13 +296,13 @@ void titleAndIconName_shouldBeInheritable(final Class<?> 
type) throws Exception
             assertEquals("inherited title", titleService.titleOf(instance));
             assertEquals(
                 new ObjectSupport.ClassPathIconResource("inherited icon"),
-                titleService.iconOf(instance, IconWhere.OBJECT_HEADER));
+                titleService.iconOf(instance, IconSize.LARGE));
 
             var domainObject = ManagedObject.adaptSingular(spec, instance);
             assertEquals("inherited title", domainObject.getTitle());
             assertEquals(
                 new ObjectSupport.ClassPathIconResource("inherited icon"),
-                iconFacet.icon(domainObject, 
IconWhere.OBJECT_HEADER).orElse(null));
+                iconFacet.icon(domainObject, IconSize.LARGE).orElse(null));
         }
     }
 
diff --git 
a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java
 
b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java
index a319df8157e..9356babc085 100644
--- 
a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java
+++ 
b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java
@@ -34,7 +34,7 @@
 
 import org.apache.causeway.applib.annotation.Where;
 import org.apache.causeway.applib.services.command.Command;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.applib.services.wrapper.WrapperFactory;
 import org.apache.causeway.applib.value.Password;
 import org.apache.causeway.applib.value.semantics.Parser;
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
index 2b19cc8f6df..6244e8e4fb1 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/mixin/HasIcon.java
@@ -21,25 +21,25 @@
 import java.util.Objects;
 import java.util.function.Consumer;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
+import org.apache.causeway.applib.services.render.ObjectIcon;
+import org.apache.causeway.applib.services.render.ObjectIconEmbedded;
+import org.apache.causeway.applib.services.render.ObjectIconFa;
+import org.apache.causeway.applib.services.render.ObjectIconUrlBased;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconFa;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
 
 @FunctionalInterface
 public interface HasIcon {
 
-    ObjectIcon getIcon(IconWhere iconWhere);
+    ObjectIcon getIcon(IconSize iconSize);
 
     default void visitIconVariant(
-        IconWhere iconWhere,
+        IconSize iconSize,
         Consumer<ObjectIconUrlBased> a,
         Consumer<ObjectIconEmbedded> b,
         Consumer<ObjectIconFa> c) {
 
-        var objectIcon = Objects.requireNonNull(getIcon(iconWhere));
+        var objectIcon = Objects.requireNonNull(getIcon(iconSize));
         if(objectIcon instanceof ObjectIconUrlBased urlBased){
             a.accept(urlBased);
         } else if(objectIcon instanceof ObjectIconEmbedded embedded){
diff --git 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
index 7312f45031f..52a54ca69c4 100644
--- 
a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
+++ 
b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java
@@ -27,7 +27,7 @@
 import org.springframework.web.bind.annotation.RestController;
 
 import org.apache.causeway.applib.annotation.Where;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.layout.component.ActionLayoutData;
 import org.apache.causeway.applib.layout.component.CollectionLayoutData;
 import org.apache.causeway.applib.layout.component.DomainObjectLayoutData;
@@ -219,7 +219,7 @@ public ResponseEntity<Object> image(
 
         var objectAdapter = getObjectAdapterElseThrowNotFound(domainType, 
instanceId,
                 roEx->_EndpointLogging.error(log, "GET 
/objects/{}/{}/object-icon", domainType, instanceId, roEx));
-        var objectIcon = objectAdapter.getIcon(IconWhere.OBJECT_HEADER);
+        var objectIcon = objectAdapter.getIcon(IconSize.MEDIUM);
 
         return _EndpointLogging.response(log, "GET 
/objects/{}/{}/object-icon", domainType, instanceId,
             responseFactory.ok(
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkTreeNode.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkTreeNode.java
index 4d287f581b3..d900f256b4f 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkTreeNode.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkTreeNode.java
@@ -28,13 +28,13 @@
 import org.apache.wicket.request.resource.ResourceReference;
 import org.jspecify.annotations.NonNull;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
+import org.apache.causeway.applib.services.render.ObjectIconEmbedded;
 import org.apache.causeway.commons.internal.base._Casts;
 import org.apache.causeway.commons.internal.collections._Lists;
 import org.apache.causeway.commons.internal.functions._Functions;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
 
 import lombok.Getter;
 
@@ -76,7 +76,7 @@ private BookmarkTreeNode(
 
         _Casts.castTo(UiObjectWkt.class, bookmarkableModel)
         .ifPresent(x->x.visitIconVariantOrElse(
-                IconWhere.TABLE_ROW,
+                IconSize.MEDIUM,
                 rref->{this.iconResourceReference = rref;},
                 embedded->{this.embedded = embedded;},
                 faLayers->{this.faLayers = faLayers;},
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
index 63a08db93a6..aad7abe638f 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/BookmarkableModel.java
@@ -24,9 +24,9 @@
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 import org.apache.causeway.applib.annotation.BookmarkPolicy;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
+import org.apache.causeway.applib.services.render.ObjectIcon;
 import org.apache.causeway.viewer.commons.model.mixin.HasIcon;
 import org.apache.causeway.viewer.commons.model.mixin.HasTitle;
 import org.apache.causeway.viewer.wicket.model.util.PageParameterUtils;
@@ -66,7 +66,7 @@ default Stream<Bookmark> streamPropertyBookmarks() {
      * I believe actions only support the former. Hence the asymmetry here.
      */
     @Override
-    default ObjectIcon getIcon(IconWhere iconWhere) {
+    default ObjectIcon getIcon(IconSize iconSize) {
         return null; // overwritten for domain objects
     }
 
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ImageResourceCache.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ImageResourceCache.java
index 7562baf2441..07329c716a0 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ImageResourceCache.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ImageResourceCache.java
@@ -22,7 +22,7 @@
 
 import org.apache.wicket.request.resource.ResourceReference;
 
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
+import org.apache.causeway.applib.services.render.ObjectIconUrlBased;
 
 public interface ImageResourceCache extends Serializable {
 
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
index ae48661a268..dc557e60717 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
@@ -31,17 +31,17 @@
 import org.jspecify.annotations.Nullable;
 
 import org.apache.causeway.applib.Identifier;
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import 
org.apache.causeway.applib.exceptions.unrecoverable.ObjectNotFoundException;
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
 import org.apache.causeway.applib.services.hint.HintStore;
+import org.apache.causeway.applib.services.render.ObjectIcon;
+import org.apache.causeway.applib.services.render.ObjectIconEmbedded;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._NullSafe;
 import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconEmbedded;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
@@ -185,18 +185,18 @@ public String getTitle() {
     }
 
     @Override
-    public ObjectIcon getIcon(IconWhere iconWhere) {
-        return getManagedObject().getIcon(iconWhere);
+    public ObjectIcon getIcon(IconSize iconSize) {
+        return getManagedObject().getIcon(iconSize);
     }
 
     public void visitIconVariantOrElse(
-            IconWhere iconWhere,
+            IconSize iconSize,
             Consumer<ResourceReference> a,
             Consumer<ObjectIconEmbedded> b,
             Consumer<FontAwesomeLayers> c,
             Runnable onNoMatch) {
         visitIconVariant(
-            iconWhere,
+            iconSize,
             urlBased->{
                 var rref = 
imageResourceCache().resourceReferenceForObjectIcon(urlBased);
                 if(rref!=null) {
diff --git 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderTestAbstract.java
 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderTestAbstract.java
index 995a36b8575..607663cc7ef 100644
--- 
a/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderTestAbstract.java
+++ 
b/viewers/wicket/ui-test/src/test/java/org/apache/causeway/viewer/wicket/ui/components/widgets/select2/ChoiceProviderTestAbstract.java
@@ -38,7 +38,7 @@ abstract class ChoiceProviderTestAbstract {
     protected void setUp() {
         mmc = MetaModelContext_forTesting.builder()
                 .memberExecutor(mock(MemberExecutorService.class))
-                .objectIconService((managedObject, iconWhere) -> null)
+                .objectIconService((managedObject, iconSize) -> null)
                 .build()
                 .withValueSemantics(new BigDecimalValueSemantics())
                 .withValueSemantics(new IntValueSemantics())
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/AttributePanelWithInlinePrompt.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/AttributePanelWithInlinePrompt.java
index e3a2b584f10..ececc96b8b6 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/AttributePanelWithInlinePrompt.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/AttributePanelWithInlinePrompt.java
@@ -29,7 +29,7 @@
 import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.core.metamodel.interactions.managed.InteractionVeto;
 import org.apache.causeway.viewer.commons.model.components.UiString;
 import org.apache.causeway.viewer.wicket.model.models.ActionModel;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/BlobOrClobAttributePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/BlobOrClobAttributePanel.java
index 69c069737c2..48cdee5255b 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/BlobOrClobAttributePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/BlobOrClobAttributePanel.java
@@ -28,7 +28,7 @@
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.resource.IResource;
 
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.applib.value.NamedWithMimeType;
 import org.apache.causeway.viewer.commons.model.components.UiString;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
index 7c2a2c2959e..ebee0be9b75 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/choices/ObjectChoicesAttributePanel.java
@@ -28,7 +28,7 @@
 import org.apache.wicket.util.convert.ConversionException;
 import org.apache.wicket.util.convert.IConverter;
 
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.viewer.commons.model.components.UiComponentType;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/image/ImageAttributePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/image/ImageAttributePanel.java
index ea0ff7bec12..35fb43059b0 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/image/ImageAttributePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/image/ImageAttributePanel.java
@@ -27,7 +27,7 @@
 import org.apache.wicket.markup.html.form.upload.FileUpload;
 import org.apache.wicket.model.IModel;
 
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.viewer.commons.model.components.UiString;
 import org.apache.causeway.viewer.wicket.model.models.FileUploadModels;
 import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java
index c4828839f91..693998ffc5e 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java
@@ -28,7 +28,7 @@
 import org.apache.wicket.model.IModel;
 
 import org.apache.causeway.applib.services.linking.DeepLinkService;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.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;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
index 2858a7a1a77..af68fbc2692 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanel.java
@@ -24,12 +24,12 @@
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.markup.html.link.AbstractLink;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.applib.layout.component.CssClassFaPosition;
+import org.apache.causeway.applib.services.render.ObjectIcon;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.commons.internal.base._Text;
-import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.object.MmTitleUtils;
@@ -64,14 +64,14 @@ class ObjectIconAndTitlePanel
     private static final String ID_OBJECT_TITLE = "objectTitle";
     private static final String ID_OBJECT_ICON = "objectIcon";
 
-    private IconWhere iconWhere;
+    private IconSize iconSize;
 
     public ObjectIconAndTitlePanel(
             final String id,
-            final IconWhere iconWhere,
+            final IconSize iconSize,
             final ObjectAdapterModel objectAdapterModel) {
         super(id, objectAdapterModel);
-        this.iconWhere = iconWhere;
+        this.iconSize = iconSize;
         guardAgainstNonEmptyAbstractSingular(objectAdapterModel);
     }
 
@@ -82,13 +82,13 @@ protected ManagedObject linkedDomainObject() {
 
     @Override
     protected void onBeforeRender() {
-        buildGui(iconWhere);
+        buildGui(iconSize);
         super.onBeforeRender();
     }
 
     @Override
-    public ObjectIcon getIcon(IconWhere iconWhere) {
-        return linkedDomainObject().getIcon(iconWhere);
+    public ObjectIcon getIcon(IconSize iconSize) {
+        return linkedDomainObject().getIcon(iconSize);
     }
 
     /**
@@ -98,19 +98,19 @@ protected void onLinkWrapperCreated(final MarkupContainer 
linkWrapper) {}
 
     // -- HELPER
 
-    private void buildGui(IconWhere iconWhere) {
-        addLinkWrapper(iconWhere);
+    private void buildGui(IconSize iconSize) {
+        addLinkWrapper(iconSize);
         setOutputMarkupId(true);
     }
 
-    private void addLinkWrapper(IconWhere iconWhere) {
+    private void addLinkWrapper(IconSize iconSize) {
         var linkWrapper = Wkt.container(ID_OBJECT_LINK_WRAPPER);
-        linkWrapper.addOrReplace(createLinkWithIconAndTitle(iconWhere));
+        linkWrapper.addOrReplace(createLinkWithIconAndTitle(iconSize));
         addOrReplace(linkWrapper);
         onLinkWrapperCreated(linkWrapper);
     }
 
-    private AbstractLink createLinkWithIconAndTitle(IconWhere iconWhere) {
+    private AbstractLink createLinkWithIconAndTitle(IconSize iconSize) {
         final ManagedObject linkedDomainObject = linkedDomainObject();
         final AbstractLink link = 
createDynamicallyVisibleLink(linkedDomainObject);
 
@@ -123,11 +123,11 @@ private AbstractLink createLinkWithIconAndTitle(IconWhere 
iconWhere) {
             Wkt.labelAdd(link, ID_OBJECT_TITLE, titleAbbreviated("(no 
object)"));
         } else {
             HasIcon.super.visitIconVariant(
-                iconWhere,
+                iconSize,
                 iconUrlBased->{
                     Wkt.imageAddCachable(link, ID_OBJECT_ICON,
                         
getImageResourceCache().resourceReferenceForObjectIcon(iconUrlBased))
-                        .add(cssClassNameModifier("objectIcon", iconWhere));
+                        .add(cssClassNameModifier("objectIcon", iconSize));
                     WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
                     WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
                 },
@@ -135,7 +135,7 @@ private AbstractLink createLinkWithIconAndTitle(IconWhere 
iconWhere) {
                     // for embedded images we use CSS class 
'objectIconEmbedded' (instead of 'objectIcon')
                     // which allows to render them differently e.g. don't 
constrain image sizes, as these should be driven by embedded data
                     Wkt.imageAddEmbedded(link, ID_OBJECT_ICON, 
iconEmbedded.dataUri())
-                        .add(cssClassNameModifier("objectIconEmbedded", 
iconWhere));
+                        .add(cssClassNameModifier("objectIconEmbedded", 
iconSize));
                     WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
                     WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
                 },
@@ -144,12 +144,12 @@ private AbstractLink createLinkWithIconAndTitle(IconWhere 
iconWhere) {
                     WktComponents.permanentlyHide(link, ID_OBJECT_ICON);
                     
if(CssClassFaPosition.isLeftOrUnspecified(faLayers.position())) {
                         Wkt.faIconLayersAdd(link, ID_OBJECT_FONT_AWESOME_LEFT, 
faLayers)
-                            .add(cssClassNameModifier("objectIconFa", 
iconWhere));
+                            .add(cssClassNameModifier("objectIconFa", 
iconSize));
                         WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_RIGHT);
                     } else {
                         WktComponents.permanentlyHide(link, 
ID_OBJECT_FONT_AWESOME_LEFT);
                         Wkt.faIconLayersAdd(link, 
ID_OBJECT_FONT_AWESOME_RIGHT, faLayers)
-                            .add(cssClassNameModifier("objectIconFa", 
iconWhere));
+                            .add(cssClassNameModifier("objectIconFa", 
iconSize));
                     }
                 });
 
@@ -171,8 +171,8 @@ private AbstractLink createLinkWithIconAndTitle(IconWhere 
iconWhere) {
         return link;
     }
 
-    private CssClassNameModifier cssClassNameModifier(String primaryCssClass, 
IconWhere iconWhere) {
-        return new CssClassNameModifier(primaryCssClass, primaryCssClass + "-" 
+ iconWhere.name().toLowerCase());
+    private CssClassNameModifier cssClassNameModifier(String primaryCssClass, 
IconSize iconSize) {
+        return new CssClassNameModifier(primaryCssClass, primaryCssClass + "-" 
+ iconSize.name().toLowerCase());
     }
 
     private boolean isTitleSuppressed() {
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
index a263b5c249d..35be61c5a5f 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconAndTitlePanelFactory.java
@@ -21,7 +21,7 @@
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
 import org.apache.causeway.viewer.commons.model.components.UiComponentType;
@@ -93,7 +93,7 @@ public Component createComponent(final String id, final 
IModel<?> model) {
             throw _Exceptions.unexpectedCodeReach();
         }
 
-        return new ObjectIconAndTitlePanel(id, IconWhere.TABLE_ROW, 
objectAdapterModel);
+        return new ObjectIconAndTitlePanel(id, IconSize.MEDIUM, 
objectAdapterModel);
     }
 
     /**
@@ -103,7 +103,7 @@ public Component createComponent(final String id, final 
IModel<?> model) {
     public static Component entityIconAndTitlePanel(
             final String componentId,
             final ObjectAdapterModel objectAdapterModel) {
-        return new ObjectIconAndTitlePanel(componentId, IconWhere.TABLE_ROW, 
objectAdapterModel);
+        return new ObjectIconAndTitlePanel(componentId, IconSize.MEDIUM, 
objectAdapterModel);
     }
 
 }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanel.java
index 1c545901299..73e79cc15b5 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanel.java
@@ -20,7 +20,7 @@
 
 import org.apache.wicket.MarkupContainer;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
 import 
org.apache.causeway.viewer.wicket.ui.components.widgets.zclip.ZeroClipboardPanel;
 
@@ -34,8 +34,8 @@ class ObjectIconTitleAndCopyLinkPanel extends 
ObjectIconAndTitlePanel {
 
     private static final String ID_COPY_LINK = "copyLink";
 
-    public ObjectIconTitleAndCopyLinkPanel(final String id, final IconWhere 
iconWhere, final UiObjectWkt objectModel) {
-        super(id, iconWhere, objectModel);
+    public ObjectIconTitleAndCopyLinkPanel(final String id, final IconSize 
iconSize, final UiObjectWkt objectModel) {
+        super(id, iconSize, objectModel);
     }
 
     @Override
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanelFactory.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanelFactory.java
index 0331be1c539..74a713e4374 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanelFactory.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/icontitle/ObjectIconTitleAndCopyLinkPanelFactory.java
@@ -21,7 +21,7 @@
 import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
-import org.apache.causeway.applib.annotation.ObjectSupport.IconWhere;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
 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.components.object.ObjectComponentFactoryAbstract;
@@ -39,6 +39,6 @@ public ObjectIconTitleAndCopyLinkPanelFactory() {
     @Override
     public Component createComponent(final String id, final IModel<?> model) {
         final UiObjectWkt objectModel = (UiObjectWkt) model;
-        return new ObjectIconTitleAndCopyLinkPanel(id, 
IconWhere.OBJECT_HEADER, objectModel);
+        return new ObjectIconTitleAndCopyLinkPanel(id, IconSize.LARGE, 
objectModel);
     }
 }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/objectsimplelink/ObjectLinkSimplePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/objectsimplelink/ObjectLinkSimplePanel.java
index a00bb9e277f..5c1cb3db1bb 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/objectsimplelink/ObjectLinkSimplePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/objectsimplelink/ObjectLinkSimplePanel.java
@@ -24,7 +24,7 @@
 import org.apache.wicket.model.IModel;
 
 import org.apache.causeway.applib.services.i18n.TranslationContext;
-import 
org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
+import 
org.apache.causeway.applib.services.render.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/common/bootstrap/css/bootstrap-overrides-all-v2.css
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/common/bootstrap/css/bootstrap-overrides-all-v2.css
index fff69797f23..d234fb7a45b 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/common/bootstrap/css/bootstrap-overrides-all-v2.css
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/common/bootstrap/css/bootstrap-overrides-all-v2.css
@@ -171,16 +171,20 @@ footer > .navbar {
     margin: 0;
 }
 
-/* from ObjectIconAndTitlePanel */
+/* objetc icon  */
 
-.objectIconAndTitlePanel img.objectIcon-object_header {
+img.objectIcon-large {
     max-width: 2rem;
     max-height: 2rem;
 }
-.objectIconAndTitlePanel img.objectIcon-table_row {
+img.objectIcon-medium {
     max-width: 1.5rem;
     max-height: 1.5rem;
 }
+img.objectIcon-small {
+    max-width: 1.0rem;
+    max-height: 1.0rem;
+}
 
 /* from ActionPromptHeaderPanel */
 
@@ -198,7 +202,7 @@ footer > .navbar {
 
 .simpleClipboardPanel div.inner {
     margin: 20px;
-    width:640px;
+    width: 640px;
 }
 
 .simpleClipboardPanel div.inner p.scalarName {
diff --git 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
index 5d9101d5472..11c256b51dd 100644
--- 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
+++ 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/CausewayModuleViewerWicketViewer.java
@@ -30,6 +30,7 @@
 import org.apache.causeway.viewer.wicket.viewer.services.DeepLinkServiceWicket;
 import 
org.apache.causeway.viewer.wicket.viewer.services.HintStoreUsingWicketSession;
 import 
org.apache.causeway.viewer.wicket.viewer.services.ImageResourceCacheClassPath;
+import 
org.apache.causeway.viewer.wicket.viewer.services.ObjectRenderServiceWicket;
 import org.apache.causeway.viewer.wicket.viewer.webmodule.WebModuleWicket;
 import 
org.apache.causeway.viewer.wicket.viewer.wicketapp.config.BootstrapInitWkt;
 import 
org.apache.causeway.viewer.wicket.viewer.wicketapp.config.DatatablesNetInitWkt;
@@ -60,6 +61,7 @@
         // @Service's
         BookmarkUiServiceWicket.class,
         DeepLinkServiceWicket.class,
+        ObjectRenderServiceWicket.class,
         WebModuleWicket.class,
 
         PageClassListDefault.AutoConfiguration.class,
diff --git 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
index a1820f15fed..2880b74e38d 100644
--- 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
+++ 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ImageResourceCacheClassPath.java
@@ -36,7 +36,7 @@
 import org.springframework.core.annotation.Order;
 
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
-import 
org.apache.causeway.core.metamodel.facets.object.icon.ObjectIconUrlBased;
+import org.apache.causeway.applib.services.render.ObjectIconUrlBased;
 import org.apache.causeway.viewer.wicket.model.models.ImageResourceCache;
 import 
org.apache.causeway.viewer.wicket.viewer.CausewayModuleViewerWicketViewer;
 
diff --git 
a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ObjectRenderServiceWicket.java
 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ObjectRenderServiceWicket.java
new file mode 100644
index 00000000000..d9b3b0f2950
--- /dev/null
+++ 
b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/services/ObjectRenderServiceWicket.java
@@ -0,0 +1,75 @@
+/*
+ *  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.viewer.services;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.resource.ResourceReference;
+import org.jspecify.annotations.Nullable;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import org.apache.causeway.applib.annotation.PriorityPrecedence;
+import org.apache.causeway.applib.annotation.ObjectSupport.IconSize;
+import org.apache.causeway.applib.services.render.ObjectIcon;
+import org.apache.causeway.applib.services.render.ObjectIconEmbedded;
+import org.apache.causeway.applib.services.render.ObjectIconFa;
+import org.apache.causeway.applib.services.render.ObjectIconUrlBased;
+import org.apache.causeway.applib.services.render.ObjectRenderService;
+import org.apache.causeway.viewer.wicket.model.models.ImageResourceCache;
+import 
org.apache.causeway.viewer.wicket.viewer.CausewayModuleViewerWicketViewer;
+
+@Service
+@Named(CausewayModuleViewerWicketViewer.NAMESPACE + 
".ObjectRenderServiceWicket")
[email protected](PriorityPrecedence.EARLY)
+@Qualifier("Wicket")
+public class ObjectRenderServiceWicket implements ObjectRenderService {
+
+    @Inject private ImageResourceCache imageResourceCache;
+
+    @Override
+    public String iconToHtml(@Nullable final ObjectIcon objectIcon, final 
IconSize iconSize) {
+        if(objectIcon instanceof ObjectIconUrlBased urlBased) {
+            ResourceReference resourceReference = 
imageResourceCache.resourceReferenceForObjectIcon(urlBased);
+            // Get the URL for the ResourceReference
+            String iconUrl = RequestCycle.get().urlFor(resourceReference, 
null).toString();
+            String fullUrl = 
RequestCycle.get().getUrlRenderer().renderFullUrl(Url.parse(iconUrl));
+
+            return "<img %s %s/>".formatted(cssClass("objectIcon", iconSize), 
src(fullUrl));
+        }
+        if(objectIcon instanceof ObjectIconEmbedded embedded)
+            return "<img %s %s/>".formatted(cssClass("objectIconEmbedded", 
iconSize), src(embedded.dataUri().toExternalForm()));
+        if(objectIcon instanceof ObjectIconFa fa)
+            return fa.fontAwesomeLayers().toHtml();
+
+        return null;
+    }
+
+    private String src(final String url) {
+        return "src=\"%s\"".formatted(url);
+    }
+    private String cssClass(final String primaryCssClass, final IconSize 
iconSize) {
+        return "class=\"%s %s-%s\"".formatted(
+            primaryCssClass, primaryCssClass, iconSize.name().toLowerCase());
+    }
+}

Reply via email to