You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/07/05 06:42:59 UTC

[isis] branch master updated: ISIS-2340: fx: flesh out prototyping decorator

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

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


The following commit(s) were added to refs/heads/master by this push:
     new b033d88  ISIS-2340: fx: flesh out prototyping decorator
b033d88 is described below

commit b033d88337c67bea9c5a047a24bd95e82cc23d10
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Jul 5 08:42:35 2020 +0200

    ISIS-2340: fx: flesh out prototyping decorator
---
 .../javafx/ui/IsisModuleIncViewerJavaFxUi.java     |  14 ++-
 .../javafx/ui/components/UiComponentFactoryFx.java |  16 ++-
 .../prototyping/PrototypingButtonDecorator.java    |  54 +++++++++
 .../PrototypingFormFieldDecorator.java}            |  50 ++------
 .../prototyping/PrototypingInfoPopupProvider.java  | 135 +++++++++++++++++++++
 .../javafx/ui/services/PrototypingInfoService.java | 112 -----------------
 .../prototyping/PrototypingDecorator.java          |   8 +-
 .../decorator/prototyping/PrototypingUiModel.java  |  74 +++++++++++
 .../isis/viewer/wicket/ui/util/Decorators.java     |   6 +-
 9 files changed, 306 insertions(+), 163 deletions(-)

diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
index ff7b9b5..bdefdb2 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/IsisModuleIncViewerJavaFxUi.java
@@ -22,17 +22,18 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
 
 import org.apache.isis.incubator.viewer.javafx.model.events.IsisModuleIncViewerJavaFxModel;
-import org.apache.isis.incubator.viewer.javafx.ui.components.PrototypingDecorator;
 import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentFactoryFx;
 import org.apache.isis.incubator.viewer.javafx.ui.components.markup.MarkupFieldFactory;
 import org.apache.isis.incubator.viewer.javafx.ui.components.other.FallbackFieldFactory;
 import org.apache.isis.incubator.viewer.javafx.ui.components.text.TextFieldFactory;
+import org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping.PrototypingButtonDecorator;
+import org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping.PrototypingFormFieldDecorator;
+import org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping.PrototypingInfoPopupProvider;
 import org.apache.isis.incubator.viewer.javafx.ui.main.UiActionHandler;
 import org.apache.isis.incubator.viewer.javafx.ui.main.UiBuilder;
 import org.apache.isis.incubator.viewer.javafx.ui.main.UiController;
 import org.apache.isis.incubator.viewer.javafx.ui.services.DecoratorServiceDefault;
 import org.apache.isis.incubator.viewer.javafx.ui.services.IconServiceDefault;
-import org.apache.isis.incubator.viewer.javafx.ui.services.PrototypingInfoService;
 import org.apache.isis.incubator.viewer.javafx.ui.services.UiContexDefault;
 import org.apache.isis.viewer.common.model.IsisModuleViewerCommon;
 
@@ -50,16 +51,19 @@ import org.apache.isis.viewer.common.model.IsisModuleViewerCommon;
         UiBuilder.class,
         UiController.class,
         
-        // component factories
+        // component factories 
         TextFieldFactory.class,
         MarkupFieldFactory.class,
         FallbackFieldFactory.class,
         
+        // decorators
+        PrototypingButtonDecorator.class,
+        PrototypingFormFieldDecorator.class,
+        PrototypingInfoPopupProvider.class,
+        
         // @Service's
         UiComponentFactoryFx.class,
         UiActionHandler.class,
-        PrototypingInfoService.class,
-        PrototypingDecorator.class,
         
         UiContexDefault.class,
         IconServiceDefault.class,
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/UiComponentFactoryFx.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/UiComponentFactoryFx.java
index 099d0c5..95f2ab7 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/UiComponentFactoryFx.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/UiComponentFactoryFx.java
@@ -31,7 +31,10 @@ import org.apache.isis.core.commons.internal.environment.IsisSystemEnvironment;
 import org.apache.isis.core.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.incubator.viewer.javafx.ui.components.form.FormField;
+import org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping.PrototypingButtonDecorator;
+import org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping.PrototypingFormFieldDecorator;
 import org.apache.isis.viewer.common.model.binding.UiComponentFactory;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingUiModel;
 
 import javafx.scene.Node;
 import javafx.scene.control.Button;
@@ -42,7 +45,8 @@ import lombok.val;
 public class UiComponentFactoryFx implements UiComponentFactory<FormField> {
 
     private final boolean isPrototyping;
-    private final PrototypingDecorator prototypingDecorator;
+    private final PrototypingButtonDecorator prototypingButtonDecorator;
+    private final PrototypingFormFieldDecorator prototypingFormFieldDecorator;
     private final ChainOfResponsibility<Request, FormField> chainOfHandlers;
     
     /** handlers in order of precedence (debug info)*/
@@ -52,11 +56,13 @@ public class UiComponentFactoryFx implements UiComponentFactory<FormField> {
     @Inject
     private UiComponentFactoryFx(
             IsisSystemEnvironment isisSystemEnvironment,
-            PrototypingDecorator prototypingDecorator,
+            PrototypingButtonDecorator prototypingButtonDecorator,
+            PrototypingFormFieldDecorator prototypingFormFieldDecorator,
             List<UiComponentHandlerFx> handlers) {
         
         this.isPrototyping = isisSystemEnvironment.isPrototyping();
-        this.prototypingDecorator = prototypingDecorator;
+        this.prototypingButtonDecorator = prototypingButtonDecorator;
+        this.prototypingFormFieldDecorator = prototypingFormFieldDecorator;
         this.chainOfHandlers = ChainOfResponsibility.of(handlers);
         this.registeredHandlers = handlers.stream()
                 .map(Handler::getClass)
@@ -72,7 +78,7 @@ public class UiComponentFactoryFx implements UiComponentFactory<FormField> {
                         "Component Mapper failed to handle request %s", request));
         
         return isPrototyping
-                ? prototypingDecorator.decorateFormField(formField, request.getObjectFeature())
+                ? prototypingFormFieldDecorator.decorate(formField, PrototypingUiModel.of(request.getObjectFeature()))
                 : formField;
     }
     
@@ -83,7 +89,7 @@ public class UiComponentFactoryFx implements UiComponentFactory<FormField> {
         uiButton.setOnAction(event->actionEventHandler.accept(managedAction));
         
         return isPrototyping
-                ? prototypingDecorator.decorateButton(managedAction, uiButton)
+                ? prototypingButtonDecorator.decorate(uiButton, PrototypingUiModel.of(managedAction))
                 : uiButton;
     }
     
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingButtonDecorator.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingButtonDecorator.java
new file mode 100644
index 0000000..a2b52e9
--- /dev/null
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingButtonDecorator.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.incubator.viewer.javafx.model.util._fx;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingDecorator;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingUiModel;
+
+import javafx.scene.Node;
+import javafx.scene.control.Label;
+import javafx.scene.control.Tooltip;
+import javafx.scene.layout.HBox;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+@Component
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class PrototypingButtonDecorator implements PrototypingDecorator<Node> {
+
+    private final PrototypingInfoPopupProvider prototypingInfoService;
+    
+    @Override
+    public Node decorate(Node uiButton, PrototypingUiModel prototypingUiModel) {
+        val span = new HBox();
+        val prototypingLabel = _fx.add(span, new Label("ⓘ"));
+        _fx.add(span, uiButton);
+        prototypingLabel.setTooltip(new Tooltip("Inspect Metamodel"));
+        prototypingLabel.setOnMouseClicked(e->
+            prototypingInfoService.showPrototypingPopup(prototypingUiModel));
+        return span;
+    }
+
+    
+}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/PrototypingDecorator.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingFormFieldDecorator.java
similarity index 57%
rename from incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/PrototypingDecorator.java
rename to incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingFormFieldDecorator.java
index 2c5de38..c0dc130 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/PrototypingDecorator.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingFormFieldDecorator.java
@@ -16,65 +16,39 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.incubator.viewer.javafx.ui.components;
+package org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping;
 
 import javax.inject.Inject;
 
-import org.springframework.stereotype.Service;
+import org.springframework.stereotype.Component;
 
 import org.apache.isis.applib.annotation.LabelPosition;
-import org.apache.isis.core.metamodel.interactions.managed.ManagedMember;
 import org.apache.isis.incubator.viewer.javafx.model.util._fx;
-import org.apache.isis.incubator.viewer.javafx.ui.components.dialog.Dialogs;
 import org.apache.isis.incubator.viewer.javafx.ui.components.form.FormField;
-import org.apache.isis.incubator.viewer.javafx.ui.services.PrototypingInfoService;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingDecorator;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingUiModel;
 
 import javafx.scene.Node;
-import javafx.scene.control.Button;
 import javafx.scene.control.Label;
 import javafx.scene.control.Tooltip;
-import javafx.scene.layout.HBox;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.VBox;
-import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.val;
 
-@Service
+@Component
 @RequiredArgsConstructor(onConstructor_ = {@Inject})
-public class PrototypingDecorator {
-    
-    private final PrototypingInfoService prototypingInfoService;
-
-    public Node decorateButton(
-            @NonNull final ManagedMember managedAction, 
-            @NonNull final Button uiButton) {
-        
-        val span = new HBox();
-        val prototypingLabel = _fx.add(span, new Label("ⓘ"));
-        _fx.add(span, uiButton);
-        prototypingLabel.setTooltip(new Tooltip("Inspect Metamodel"));
-        prototypingLabel.setOnMouseClicked(e->showPrototypingPopup(managedAction));
-        return span;
-    }
+public class PrototypingFormFieldDecorator implements PrototypingDecorator<FormField> {
 
-    public FormField decorateFormField(
-            @NonNull final FormField formField, 
-            @NonNull final ManagedMember managedMember) {
-        
-        return DecoratingFormField.of(formField, ()->showPrototypingPopup(managedMember));
+    private final PrototypingInfoPopupProvider prototypingInfoService;
+    
+    @Override
+    public FormField decorate(final FormField formField, final PrototypingUiModel prototypingUiModel) {
+        return DecoratingFormField.of(formField, ()->
+            prototypingInfoService.showPrototypingPopup(prototypingUiModel));
     }
     
     // -- HELPER
-    
-    private void showPrototypingPopup(final ManagedMember managedMember) {
-        val infoNode = prototypingInfoService.getPrototypingInfoUiComponent(managedMember);
-        val headerText = String.format("%s: %s", 
-                managedMember.getMemberType().name(), 
-                managedMember.getName());
-        val contentText = String.format("%s", managedMember.getId());
-        Dialogs.message("Inspect Metamodel", headerText, contentText, infoNode);
-    }
 
     @RequiredArgsConstructor(staticName = "of")
     private static class DecoratingFormField implements FormField {
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingInfoPopupProvider.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingInfoPopupProvider.java
new file mode 100644
index 0000000..2cde06a
--- /dev/null
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/decorator/prototyping/PrototypingInfoPopupProvider.java
@@ -0,0 +1,135 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.incubator.viewer.javafx.ui.decorator.prototyping;
+
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.isis.core.commons.internal.collections._Maps;
+import org.apache.isis.core.commons.internal.collections._Sets;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.incubator.viewer.javafx.model.util._fx;
+import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentFactoryFx;
+import org.apache.isis.incubator.viewer.javafx.ui.components.dialog.Dialogs;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingUiModel;
+
+import javafx.beans.property.SimpleStringProperty;
+import javafx.scene.Node;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.layout.VBox;
+import lombok.RequiredArgsConstructor;
+import lombok.Value;
+import lombok.val;
+
+@Component
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class PrototypingInfoPopupProvider {
+
+    private final Provider<UiComponentFactoryFx> uiComponentFactory;
+
+    public void showPrototypingPopup(final PrototypingUiModel prototypingUiModel) {
+        val infoNode = getPrototypingInfoUiComponent(prototypingUiModel);
+        val headerText = prototypingUiModel.getFeatureFullLabel();
+        val contentText = (String)null;
+        Dialogs.message("Inspect Metamodel", headerText, contentText, infoNode);
+    }
+
+    // -- HELPER
+    
+    @Value(staticConstructor = "of")
+    private static class Info implements Comparable<Info> {
+        private final String key;
+        private final String value;
+        @Override
+        public int compareTo(Info other) {
+            return this.getKey().compareTo(other.getKey());
+        }
+    }
+    
+    private Node getPrototypingInfoUiComponent(final PrototypingUiModel prototypingUiModel) {
+
+        val infos = _Sets.<Info>newTreeSet();
+        
+        val handlerInfo = (String)uiComponentFactory.get().getRegisteredHandlers()
+                .stream()
+                .map(Class::getSimpleName)
+                .map(handlerName->" • " + handlerName)
+                .collect(Collectors.joining("\n"));
+
+        infos.add(Info.of("Handlers", handlerInfo));
+
+        prototypingUiModel.streamFeatureFacets()
+        .forEach(facet -> 
+            infos.add(Info.of(
+                    facet.facetType().getSimpleName(), 
+                    summarize(facet))));
+
+        val detailPane = new VBox();
+        TableView<Info> tableView = _fx.add(detailPane, new TableView<Info>());
+        
+        TableColumn<Info, String> column1 = new TableColumn<>("Key");
+        column1.setCellValueFactory(c->new SimpleStringProperty(c.getValue().getKey()));
+
+        TableColumn<Info, String> column2 = new TableColumn<>("Value");
+        column2.setCellValueFactory(c->new SimpleStringProperty(c.getValue().getValue()));
+
+        tableView.getColumns().add(column1);
+        tableView.getColumns().add(column2);
+        
+        infos.forEach(tableView.getItems()::add);
+        
+        tableView.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
+        
+        //TODO this is a candidate to be moved to _fx, to also account for max screen sizes
+        val scrollPane = new ScrollPane(detailPane);
+        scrollPane.fitToWidthProperty().set(true);
+        scrollPane.fitToHeightProperty().set(true);
+        scrollPane.hbarPolicyProperty().setValue(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+        scrollPane.vbarPolicyProperty().setValue(ScrollPane.ScrollBarPolicy.AS_NEEDED);
+        scrollPane.setPrefHeight(800);
+        scrollPane.setMaxHeight(800);
+        scrollPane.setPrefWidth(1200);
+        
+        tableView.prefHeightProperty().bind(scrollPane.heightProperty());
+        
+        return scrollPane;
+    }
+
+    private String summarize(Facet facet) {
+        val sb = new StringBuilder();
+        sb.append(facet.getClass().getSimpleName());
+        if(facet instanceof FacetAbstract) {
+            val attributeMap = _Maps.<String, Object>newTreeMap();
+            ((FacetAbstract)facet).appendAttributesTo(attributeMap);
+            attributeMap.forEach((k, v)->{
+                sb.append("\n • ").append(k).append(": ").append(v);    
+            });
+        }
+        return sb.toString();
+    }
+
+
+}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/services/PrototypingInfoService.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/services/PrototypingInfoService.java
deleted file mode 100644
index 25aa31b..0000000
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/services/PrototypingInfoService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.incubator.viewer.javafx.ui.services;
-
-import java.util.stream.Collectors;
-
-import javax.inject.Inject;
-import javax.inject.Provider;
-
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.core.commons.internal.base._Strings;
-import org.apache.isis.core.commons.internal.collections._Maps;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
-import org.apache.isis.core.metamodel.interactions.managed.ManagedMember;
-import org.apache.isis.incubator.viewer.javafx.model.util._fx;
-import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentFactoryFx;
-import org.apache.isis.viewer.common.model.debug.DebugUiModel;
-
-import javafx.scene.Node;
-import javafx.scene.control.Label;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.control.TextArea;
-import javafx.scene.layout.VBox;
-import lombok.val;
-
-@Service
-public class PrototypingInfoService {
-
-    @Inject private Provider<UiComponentFactoryFx> uiComponentFactory;
-
-    public Node getPrototypingInfoUiComponent(ManagedMember managedMember) {
-
-        final FacetHolder facetHolder = (managedMember instanceof ManagedAction)
-                ? ((ManagedAction) managedMember).getAction()
-                : managedMember.getSpecification();
-    
-        val debugUiModel = DebugUiModel.of(managedMember.getId())
-//                        .withProperty("ObjectFeature.specification.fullIdentifier",  spec.getFullIdentifier())
-                        .withProperty("ObjectFeature.identifier",  managedMember.getIdentifier().toString());
-
-        val handlerInfo = uiComponentFactory.get().getRegisteredHandlers()
-                .stream()
-                .map(Class::getSimpleName)
-                .map(handlerName->" • " + handlerName)
-                .collect(Collectors.joining("\n"));
-
-        debugUiModel.withProperty("Handlers", handlerInfo);
-
-        facetHolder.streamFacets()
-        .forEach(facet -> {
-            debugUiModel.withProperty(
-                    facet.facetType().getSimpleName(), 
-                    summarize(facet));
-        });
-
-        val detailPane = new VBox();
-        _fx.add(detailPane, _fx.h2(new Label(debugUiModel.getSummaryText())));
-        
-        debugUiModel.getKeyValuePairs().forEach((k, v)->{
-            _fx.add(detailPane, new Label(k));
-            val text = _fx.add(detailPane, new TextArea(v));
-            val prefHeight = 16*(1+(int)_Strings.splitThenStream(v, "\n").count());
-            text.setPrefHeight(prefHeight);
-            text.setWrapText(true);
-            text.setEditable(false);
-            text.autosize();
-        });
-        
-        val scrollPane = new ScrollPane(detailPane);
-        scrollPane.fitToWidthProperty().set(true);
-        scrollPane.fitToHeightProperty().set(true);
-        scrollPane.hbarPolicyProperty().setValue(ScrollPane.ScrollBarPolicy.NEVER);
-        scrollPane.vbarPolicyProperty().setValue(ScrollPane.ScrollBarPolicy.ALWAYS);
-        scrollPane.setPrefHeight(800);
-        scrollPane.setMaxHeight(800);
-        return scrollPane;
-    }
-
-    private String summarize(Facet facet) {
-        val sb = new StringBuilder();
-        sb.append(facet.getClass().getSimpleName());
-        if(facet instanceof FacetAbstract) {
-            val attributeMap = _Maps.<String, Object>newTreeMap();
-            ((FacetAbstract)facet).appendAttributesTo(attributeMap);
-            attributeMap.forEach((k, v)->{
-                sb.append("\n • ").append(k).append(": ").append(v);    
-            });
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingDecorator.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingDecorator.java
index 67903a6..b06209f 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingDecorator.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingDecorator.java
@@ -18,8 +18,14 @@
  */
 package org.apache.isis.viewer.common.model.decorator.prototyping;
 
+/**
+ * 
+ * When in PROTOTYPING mode adds additional UI aspects, which are otherwise (production mode) not visible.
+ *
+ * @param <T>
+ */
 public interface PrototypingDecorator<T> {
 
-    void decorate(T uiComponent);
+    T decorate(T uiComponent, PrototypingUiModel prototypingUiModel);
     
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingUiModel.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingUiModel.java
new file mode 100644
index 0000000..d58f1e7
--- /dev/null
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/decorator/prototyping/PrototypingUiModel.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.common.model.decorator.prototyping;
+
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedMember;
+import org.apache.isis.viewer.common.model.action.ActionUiMetaModel;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public class PrototypingUiModel {
+
+    private final Class<?> featureType;
+    private final String featureShortLabel;
+    private final String featureFullLabel;
+    private final Supplier<Stream<Facet>> facetStreamProvider;
+    
+    public static PrototypingUiModel of(ActionUiMetaModel actionMeta) {
+        return null; // used by wicket, not supported yet
+    }
+    
+    public static PrototypingUiModel of(ManagedAction managedAction) {
+        Class<?> featureType = managedAction.getAction().getReturnType().getCorrespondingClass();
+        String featureShortLabel = managedAction.getName();
+        String featureFullLabel = String.format("%s: %s", 
+                managedAction.getMemberType(), 
+                managedAction.getName());
+        
+        return new PrototypingUiModel(featureType, featureShortLabel, featureFullLabel,
+                managedAction.getAction()::streamFacets);
+    }
+    
+    public static PrototypingUiModel of(ManagedMember managedMember) {
+        Class<?> featureType = managedMember.getSpecification().getCorrespondingClass();
+        String featureShortLabel = managedMember.getName();
+        String featureFullLabel = String.format("%s: %s", 
+                managedMember.getMemberType(), 
+                managedMember.getName());
+        
+        return new PrototypingUiModel(featureType, featureShortLabel, featureFullLabel,
+                managedMember.getSpecification()::streamFacets);
+    }
+    
+    public Stream<Facet> streamFeatureFacets() {
+        return facetStreamProvider.get();
+    }
+    
+
+    
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Decorators.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Decorators.java
index 9dd98df..63cc834 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Decorators.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/util/Decorators.java
@@ -34,6 +34,7 @@ import org.apache.isis.viewer.common.model.decorator.disable.DisableUiModel;
 import org.apache.isis.viewer.common.model.decorator.fa.FontAwesomeDecorator;
 import org.apache.isis.viewer.common.model.decorator.fa.FontAwesomeUiModel;
 import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingDecorator;
+import org.apache.isis.viewer.common.model.decorator.prototyping.PrototypingUiModel;
 import org.apache.isis.viewer.common.model.decorator.tooltip.TooltipDecorator;
 import org.apache.isis.viewer.common.model.decorator.tooltip.TooltipUiModel;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
@@ -94,8 +95,9 @@ public class Decorators {
     
     public final static class Prototyping implements PrototypingDecorator<Component> {
         @Override
-        public void decorate(Component uiComponent) {
+        public Component decorate(Component uiComponent, PrototypingUiModel prototypingUiModel) {
             uiComponent.add(new CssClassAppender("prototype"));
+            return uiComponent;
         }
     }
     
@@ -194,7 +196,7 @@ public class Decorators {
             }
             
             if (actionMeta.isPrototyping()) {
-                getPrototypingDecorator().decorate(actionLinkUiComponent);
+                getPrototypingDecorator().decorate(actionLinkUiComponent, PrototypingUiModel.of(actionMeta));
             }
 
         }