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 2022/03/03 13:41:30 UTC

[isis] 02/02: ISIS-2877: some refactoring around scalar panels

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

commit 160728cd9cd8e4729cf03cd590a25fd74eb8ea41
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Mar 3 14:13:06 2022 +0100

    ISIS-2877: some refactoring around scalar panels
---
 .../ui/components/scalars/ScalarPanelAbstract.java | 183 ++++++++-------------
 .../scalars/ScalarPanelSelectAbstract.java         |  31 +---
 .../scalars/ScalarPanelTextFieldAbstract.java      |  93 +----------
 .../scalars/ScalarPanelWithFormFieldAbstract.java  |  96 ++++++++++-
 4 files changed, 167 insertions(+), 236 deletions(-)

diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
index 3c05472..59ecf50 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract.java
@@ -30,7 +30,6 @@ import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.feedback.ComponentFeedbackMessageFilter;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.LabeledWebMarkupContainer;
 import org.apache.wicket.model.IModel;
 import org.springframework.lang.Nullable;
 
@@ -55,7 +54,6 @@ import org.apache.isis.viewer.common.model.feature.ParameterUiModel;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
-import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.InlinePromptContext;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarPropertyModel;
@@ -71,6 +69,7 @@ import org.apache.isis.viewer.wicket.ui.components.scalars.valuechoices.ValueCho
 import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLink;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.Components;
+import org.apache.isis.viewer.wicket.ui.util.Tooltips;
 import org.apache.isis.viewer.wicket.ui.util.Wkt;
 import org.apache.isis.viewer.wicket.ui.util.Wkt.EventTopic;
 
@@ -119,6 +118,36 @@ implements ScalarModelSubscriber {
         NOTHING
     }
 
+    public static class InlinePromptConfig {
+        private final boolean supported;
+        private final Component componentToHideIfAny;
+
+        public static InlinePromptConfig supported() {
+            return new InlinePromptConfig(true, null);
+        }
+
+        public static InlinePromptConfig notSupported() {
+            return new InlinePromptConfig(false, null);
+        }
+
+        public static InlinePromptConfig supportedAndHide(final Component componentToHideIfAny) {
+            return new InlinePromptConfig(true, componentToHideIfAny);
+        }
+
+        private InlinePromptConfig(final boolean supported, final Component componentToHideIfAny) {
+            this.supported = supported;
+            this.componentToHideIfAny = componentToHideIfAny;
+        }
+
+        boolean isSupported() {
+            return supported;
+        }
+
+        Component getComponentToHideIfAny() {
+            return componentToHideIfAny;
+        }
+    }
+
     /**
      *
      * @param paramModel - the action being invoked
@@ -175,36 +204,6 @@ implements ScalarModelSubscriber {
                 : Repaint.NOTHING;
     }
 
-    public static class InlinePromptConfig {
-        private final boolean supported;
-        private final Component componentToHideIfAny;
-
-        public static InlinePromptConfig supported() {
-            return new InlinePromptConfig(true, null);
-        }
-
-        public static InlinePromptConfig notSupported() {
-            return new InlinePromptConfig(false, null);
-        }
-
-        public static InlinePromptConfig supportedAndHide(final Component componentToHideIfAny) {
-            return new InlinePromptConfig(true, componentToHideIfAny);
-        }
-
-        private InlinePromptConfig(final boolean supported, final Component componentToHideIfAny) {
-            this.supported = supported;
-            this.componentToHideIfAny = componentToHideIfAny;
-        }
-
-        boolean isSupported() {
-            return supported;
-        }
-
-        Component getComponentToHideIfAny() {
-            return componentToHideIfAny;
-        }
-    }
-
     // -- CONSTRUCTION
 
     /**
@@ -218,7 +217,7 @@ implements ScalarModelSubscriber {
     private Component componentIfCompact;
     protected final Component getComponentForCompact() { return componentIfCompact; }
     /**
-     * Builds the component to render the model when in {@link Rendering#COMPACT compact} format.
+     * Builds the component to render the model when in COMPACT format.
      * <p>Is added to {@link #scalarTypeContainer}.
      */
     protected abstract Component createComponentForCompact();
@@ -228,7 +227,7 @@ implements ScalarModelSubscriber {
     private MarkupContainer componentIfRegular;
     protected final MarkupContainer getComponentForRegular() { return componentIfRegular; }
     /**
-     * Builds the component to render the model when in {@link Rendering#REGULAR regular} format.
+     * Builds the component to render the model when in REGULAR format.
      * <p>Is added to {@link #scalarTypeContainer}.
      */
     protected abstract MarkupContainer createComponentForRegular();
@@ -258,15 +257,11 @@ implements ScalarModelSubscriber {
     @Override
     protected void onInitialize() {
         super.onInitialize();
-
         buildGuiAndCallHooks();
-
         setOutputMarkupId(true);
-
     }
 
     private void buildGuiAndCallHooks() {
-
         buildGui();
 
         final ScalarModel scalarModel = getModel();
@@ -286,7 +281,6 @@ implements ScalarModelSubscriber {
                 onInitializeEditable();
             }
         }
-
     }
 
     /**
@@ -327,9 +321,10 @@ implements ScalarModelSubscriber {
         scalarTypeContainer = Wkt.containerAdd(this, ID_SCALAR_TYPE_CONTAINER);
         Wkt.cssAppend(scalarTypeContainer, getCssClassName());
 
-        this.componentIfCompact = createComponentForCompact();
-        this.componentIfRegular = createComponentForRegular();
-        componentIfRegular.setOutputMarkupId(true);
+        componentIfRegular = createComponentForRegular();
+        componentIfCompact = createComponentForCompact();
+
+        componentIfRegular.setOutputMarkupId(true); // enable as AJAX target
 
         scalarTypeContainer.addOrReplace(componentIfCompact, componentIfRegular);
 
@@ -345,13 +340,13 @@ implements ScalarModelSubscriber {
         .map(LinkAndLabelFactory.forPropertyOrParameter(scalarModel))
         .collect(Can.toCan());
 
-        final InlinePromptConfig inlinePromptConfig = getInlinePromptConfig();
+        val inlinePromptConfig = getInlinePromptConfig();
         if(inlinePromptConfig.isSupported()) {
 
-            this.scalarIfRegularInlinePromptForm = createInlinePromptForm();
-            scalarTypeContainer.addOrReplace(scalarIfRegularInlinePromptForm);
-            inlinePromptLink = createInlinePromptLink();
-            componentIfRegular.add(inlinePromptLink);
+            scalarTypeContainer
+                .addOrReplace(scalarIfRegularInlinePromptForm = createInlinePromptForm());
+            componentIfRegular
+                .add(inlinePromptLink = createInlinePromptLink());
 
             // even if this particular scalarModel (property) is not configured for inline edits,
             // it's possible that one of the associated actions is.  Thus we set the prompt context
@@ -405,7 +400,22 @@ implements ScalarModelSubscriber {
         addEditPropertyTo(componentIfRegular);
         addFeedbackOnlyTo(componentIfRegular, getValidationFeedbackReceiver());
 
-        getRendering().buildGui(this);
+        switch(scalarModel.getRenderingHint()) {
+        case REGULAR:
+            //componentIfRegular = createComponentForRegular();
+            //componentIfCompact = Wkt.container(ID_SCALAR_IF_COMPACT); // empty component
+            componentIfRegular.setVisible(true);
+            componentIfCompact.setVisible(false);
+            break;
+        default:
+            //componentIfRegular = Wkt.container(ID_SCALAR_IF_REGULAR); // empty component
+            //componentIfCompact = createComponentForCompact();
+            componentIfRegular.setVisible(false);
+            componentIfCompact.setVisible(true);
+            Components.permanentlyHide(componentIfRegular, ID_SCALAR_NAME);
+            break;
+        }
+
         addCssFromMetaModel();
 
         notifyOnChange(this);
@@ -473,12 +483,8 @@ implements ScalarModelSubscriber {
      */
     @Override
     protected void onConfigure() {
-
-        final ScalarModel scalarModel = getModel();
-
-        final boolean hidden = scalarModel.whetherHidden();
+        final boolean hidden = scalarModel().whetherHidden();
         setVisibilityAllowed(!hidden);
-
         super.onConfigure();
     }
 
@@ -548,72 +554,22 @@ implements ScalarModelSubscriber {
     public void onError(final AjaxRequestTarget target, final ScalarPanelAbstract scalarPanel) {
     }
 
-
-    // ///////////////////////////////////////////////////////////////////
-
-
-    public enum Rendering {
-        /**
-         * Does not show labels, eg for use in tables
-         */
-        COMPACT {
-            @Override
-            public String getLabelCaption(final LabeledWebMarkupContainer labeledContainer) {
-                return "";
-            }
-
-            @Override
-            public void buildGui(final ScalarPanelAbstract panel) {
-                panel.componentIfCompact.setVisible(true);
-                panel.componentIfRegular.setVisible(false);
-                Components.permanentlyHide(panel.componentIfRegular, ID_SCALAR_NAME);
-            }
-
-        },
-        /**
-         * Does show labels, eg for use in forms.
-         */
-        REGULAR {
-            @Override
-            public String getLabelCaption(final LabeledWebMarkupContainer labeledContainer) {
-                return labeledContainer.getLabel().getObject();
-            }
-
-            @Override
-            public void buildGui(final ScalarPanelAbstract panel) {
-                panel.componentIfRegular.setVisible(true);
-                panel.componentIfCompact.setVisible(false);
-            }
-
-        };
-
-        public abstract String getLabelCaption(LabeledWebMarkupContainer labeledContainer);
-
-        public abstract void buildGui(ScalarPanelAbstract panel);
-
-        private static Rendering renderingFor(final EntityModel.RenderingHint renderingHint) {
-            return renderingHint.isRegular()? Rendering.REGULAR :Rendering.COMPACT;
-        }
-    }
-
-    protected Rendering getRendering() {
-        return Rendering.renderingFor(scalarModel.getRenderingHint());
-    }
-
     // ///////////////////////////////////////////////////////////////////
 
-    protected Label createScalarName(final String id, final String labelCaption) {
-        final Label scalarName = Wkt.label(id, labelCaption);
-        final ScalarModel scalarModel = getModel();
+    protected Label createScalarNameLabel(final String id, final IModel<String> labelCaption) {
+        final Label scalarNameLabel = Wkt.label(id, labelCaption);
+        val scalarModel = scalarModel();
         if(scalarModel.isRequired()
                 && scalarModel.isEnabled()) {
-            final String label = scalarName.getDefaultModelObjectAsString();
+            final String label = scalarNameLabel.getDefaultModelObjectAsString();
             if(!_Strings.isNullOrEmpty(label)) {
-                Wkt.cssAppend(scalarName, "mandatory");
+                Wkt.cssAppend(scalarNameLabel, "mandatory");
             }
         }
-        scalarName.setEscapeModelStrings(true);
-        return scalarName;
+        scalarNameLabel.setEscapeModelStrings(true);
+        scalarModel.getDescribedAs()
+            .ifPresent(describedAs->Tooltips.addTooltip(scalarNameLabel, describedAs));
+        return scalarNameLabel;
     }
 
     /**
@@ -686,7 +642,6 @@ implements ScalarModelSubscriber {
         target.add(scalarTypeContainer);
 
         Wkt.focusOnMarkerAttribute(scalarIfRegularInlinePromptForm, target);
-
     }
 
     private void switchFormForInlinePrompt(final AjaxRequestTarget target) {
@@ -706,10 +661,8 @@ implements ScalarModelSubscriber {
     protected void onSwitchFormForInlinePrompt(
             final WebMarkupContainer inlinePromptForm,
             final AjaxRequestTarget target) {
-
     }
 
-
     // ///////////////////////////////////////////////////////////////////
 
     protected void addEditPropertyTo(
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelectAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelectAbstract.java
index de11472..0f8c985 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelectAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelectAbstract.java
@@ -68,36 +68,21 @@ extends ScalarPanelAbstract {
         return select2;
     }
 
-    protected FormGroup createFormGroupAndName(
-            final FormComponent<?> component,
-            final String formGroupId, final String nameId) {
-        final FormGroup formGroup = new FormGroup(formGroupId, component);
-        formGroup.add(component);
-
-        final String labelCaption = getRendering().getLabelCaption(select2.asComponent());
-        final Label scalarName = createScalarName(nameId, labelCaption);
-
-        getModel()
-        .getDescribedAs()
-        .ifPresent(describedAs->Tooltips.addTooltip(scalarName, describedAs));
-
-        formGroup.addOrReplace(scalarName);
-        return formGroup;
-    }
-
     protected FormGroup createFormGroup(final FormComponent<?> formComponent) {
+        val scalarModel = scalarModel();
+        val friendlyNameModel = Model.of(scalarModel.getFriendlyName());
+
         setOutputMarkupId(true);
         select2.asComponent().setOutputMarkupId(true);
+        select2.setLabel(friendlyNameModel);
 
-        final String name = scalarModel().getFriendlyName();
-        select2.setLabel(Model.of(name));
-
-        final FormGroup formGroup = createFormGroupAndName(formComponent, ID_SCALAR_IF_REGULAR, ID_SCALAR_NAME);
+        final FormGroup formGroup = new FormGroup(ID_SCALAR_IF_REGULAR, formComponent);
+        formGroup.add(formComponent);
+        formGroup.addOrReplace(createScalarNameLabel(ID_SCALAR_NAME, friendlyNameModel));
 
         addStandardSemantics();
 
-        final ScalarModel model = getModel();
-        if(model.isRequired() && model.isEnabled()) {
+        if(scalarModel.isRequired() && scalarModel.isEnabled()) {
             Wkt.cssAppend(formGroup, "mandatory");
         }
         return formGroup;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index fa8595e..b6c668b 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -20,11 +20,9 @@ package org.apache.isis.viewer.wicket.ui.components.scalars;
 
 import java.io.Serializable;
 import java.util.Locale;
-import java.util.Optional;
 
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.AbstractTextComponent;
 import org.apache.wicket.markup.html.form.FormComponent;
@@ -46,7 +44,6 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
-import org.apache.isis.viewer.wicket.ui.util.Tooltips;
 import org.apache.isis.viewer.wicket.ui.util.Wkt;
 
 import lombok.AccessLevel;
@@ -57,18 +54,12 @@ import lombok.val;
 /**
  * Adapter for {@link PanelAbstract panel}s that use a {@link ScalarModel} as
  * their backing model.
- *
  * <p>
  * Supports the concept of being
- * {@link org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract.Rendering#COMPACT}
- * (eg within a table) or
- * {@link org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract.Rendering#REGULAR regular}
- * (eg within a form).
- * </p>
- *
+ * COMPACT (eg within a table) or
+ * REGULAR (eg within a form).
  * <p>
  * This implementation is for panels that use a textfield/text area.
- * </p>
  */
 public abstract class ScalarPanelTextFieldAbstract<T extends Serializable>
 extends ScalarPanelWithFormFieldAbstract
@@ -230,9 +221,7 @@ implements TextFieldValueModel.ScalarModelProvider {
     // --
 
     /**
-     * Builds the component to render the model when in
-     * {@link org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract.Rendering#COMPACT}
-     * format.
+     * Builds the component to render the model when in COMPACT format.
      * <p>
      * The (textual) default implementation uses a {@link Label}.
      * However, it may be overridden if required.
@@ -269,11 +258,6 @@ implements TextFieldValueModel.ScalarModelProvider {
     // //////////////////////////////////////
 
     @Override
-    protected InlinePromptConfig getInlinePromptConfig() {
-        return InlinePromptConfig.supportedAndHide(getFormComponent());
-    }
-
-    @Override
     protected IModel<String> obtainInlinePromptModel() {
         IModel<?> model = getFormComponent().getModel();
         // must be "live", for ajax updates.
@@ -307,77 +291,6 @@ implements TextFieldValueModel.ScalarModelProvider {
 
     // //////////////////////////////////////
 
-
-    @Override
-    protected void onInitializeNotEditable() {
-        super.onInitializeNotEditable();
-
-        getFormComponent().setEnabled(false);
-
-        if(getWicketViewerSettings().isReplaceDisabledTagWithReadonlyTag()) {
-            Wkt.behaviorAddReplaceDisabledTagWithReadonlyTag(getFormComponent());
-        }
-
-        clearTooltip();
-    }
-
-    @Override
-    protected void onInitializeReadonly(final String disableReason) {
-        super.onInitializeReadonly(disableReason);
-
-        getFormComponent().setEnabled(false);
-
-        if(getWicketViewerSettings().isReplaceDisabledTagWithReadonlyTag()) {
-            Wkt.behaviorAddReplaceDisabledTagWithReadonlyTag(getFormComponent());
-        }
-
-        inlinePromptLink.setEnabled(false);
-
-        setTooltip(disableReason);
-    }
-
-    @Override
-    protected void onInitializeEditable() {
-        super.onInitializeEditable();
-        getFormComponent().setEnabled(true);
-        inlinePromptLink.setEnabled(true);
-        clearTooltip();
-    }
-
-    @Override
-    protected void onNotEditable(final String disableReason, final Optional<AjaxRequestTarget> target) {
-        getFormComponent().setEnabled(false);
-        inlinePromptLink.setEnabled(false);
-        setTooltip(disableReason);
-        target.ifPresent(ajax->{
-            ajax.add(getFormComponent());
-            ajax.add(inlinePromptLink);
-        });
-    }
-
-    @Override
-    protected void onEditable(final Optional<AjaxRequestTarget> target) {
-        getFormComponent().setEnabled(true);
-        inlinePromptLink.setEnabled(true);
-        clearTooltip();
-        target.ifPresent(ajax->{
-            ajax.add(getFormComponent());
-            ajax.add(inlinePromptLink);
-        });
-    }
-
-    private void setTooltip(final String tooltip) {
-        Tooltips.addTooltip(getFormComponent(), tooltip);
-        Tooltips.addTooltip(inlinePromptLink, tooltip);
-    }
-
-    private void clearTooltip() {
-        Tooltips.clearTooltip(getFormComponent());
-        Tooltips.clearTooltip(inlinePromptLink);
-    }
-
-    // //////////////////////////////////////
-
     private static Integer getMaxLengthOf(final @NonNull ScalarModel model) {
         return model.getScalarTypeSpec()
                 .lookupFacet(MaxLengthFacet.class)
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelWithFormFieldAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelWithFormFieldAbstract.java
index 88480ca..2cf2cc7 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelWithFormFieldAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelWithFormFieldAbstract.java
@@ -18,14 +18,17 @@
  */
 package org.apache.isis.viewer.wicket.ui.components.scalars;
 
+import java.util.Optional;
+
 import org.apache.wicket.Component;
 import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.form.FormComponent;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.validation.IValidatable;
 import org.apache.wicket.validation.IValidator;
 import org.apache.wicket.validation.ValidationError;
+import org.springframework.lang.Nullable;
 
 import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
@@ -55,7 +58,9 @@ extends ScalarPanelAbstract {
     // -- FORM COMPONENT
 
     private FormComponent<?> formComponent;
+    @Nullable
     protected final FormComponent<?> getFormComponent() { return formComponent; }
+
     /**
      * Builds the component to render the form field.
      */
@@ -67,8 +72,10 @@ extends ScalarPanelAbstract {
     protected final MarkupContainer createComponentForRegular() {
         val scalarModel = scalarModel();
 
+        val friendlyNameModel = Model.of(scalarModel.getFriendlyName());
+
         formComponent = createFormComponent(scalarModel);
-        formComponent.setLabel(Model.of(scalarModel.getFriendlyName()));
+        formComponent.setLabel(friendlyNameModel);
 
         final FormGroup formGroup = new FormGroup(ID_SCALAR_IF_REGULAR, formComponent);
         formGroup.add(formComponent);
@@ -79,12 +86,7 @@ extends ScalarPanelAbstract {
             Wkt.cssAppend(formGroup, "mandatory");
         }
 
-        final String labelCaption = getRendering().getLabelCaption(formComponent);
-        final Label scalarName = createScalarName(ID_SCALAR_NAME, labelCaption);
-        formGroup.add(scalarName);
-
-        scalarModel.getDescribedAs()
-            .ifPresent(describedAs->Tooltips.addTooltip(scalarName, describedAs));
+        formGroup.add(createScalarNameLabel(ID_SCALAR_NAME, friendlyNameModel));
 
         formComponent.add(createValidator(scalarModel));
 
@@ -125,4 +127,82 @@ extends ScalarPanelAbstract {
         };
     }
 
+    @Override
+    protected InlinePromptConfig getInlinePromptConfig() {
+        return getFormComponent()!=null
+                ? InlinePromptConfig.supportedAndHide(getFormComponent())
+                : InlinePromptConfig.notSupported();
+    }
+
+    @Override
+    protected void onInitializeNotEditable() {
+        if(getFormComponent()!=null) {
+            //keep inlinePromptLink (if any) enabled
+            getFormComponent().setEnabled(false);
+        }
+        if(getWicketViewerSettings().isReplaceDisabledTagWithReadonlyTag()) {
+            Wkt.behaviorAddReplaceDisabledTagWithReadonlyTag(getFormComponent());
+        }
+        clearTooltip();
+    }
+
+    @Override
+    protected void onInitializeReadonly(final String disableReason) {
+        formComponentEnable(false);
+        if(getWicketViewerSettings().isReplaceDisabledTagWithReadonlyTag()) {
+            Wkt.behaviorAddReplaceDisabledTagWithReadonlyTag(getFormComponent());
+        }
+        setTooltip(disableReason);
+    }
+
+    @Override
+    protected void onInitializeEditable() {
+        formComponentEnable(true);
+        clearTooltip();
+    }
+
+    @Override
+    protected void onNotEditable(final String disableReason, final Optional<AjaxRequestTarget> target) {
+        formComponentEnable(false);
+        setTooltip(disableReason);
+        target.ifPresent(this::formComponentAddTo);
+    }
+
+    @Override
+    protected void onEditable(final Optional<AjaxRequestTarget> target) {
+        formComponentEnable(true);
+        clearTooltip();
+        target.ifPresent(this::formComponentAddTo);
+    }
+
+    // -- HELPER
+
+    private void formComponentEnable(final boolean b) {
+        if(getFormComponent()!=null) {
+            getFormComponent().setEnabled(b);
+        }
+        if(inlinePromptLink!=null) {
+            inlinePromptLink.setEnabled(b);
+        }
+    }
+
+    private void formComponentAddTo(final AjaxRequestTarget ajax) {
+        if(getFormComponent()!=null) {
+            ajax.add(getFormComponent());
+        }
+        if(inlinePromptLink!=null) {
+            ajax.add(inlinePromptLink);
+        }
+    }
+
+    private void setTooltip(final String tooltip) {
+        Tooltips.addTooltip(getFormComponent(), tooltip);
+        Tooltips.addTooltip(inlinePromptLink, tooltip);
+    }
+
+    private void clearTooltip() {
+        Tooltips.clearTooltip(getFormComponent());
+        Tooltips.clearTooltip(inlinePromptLink);
+    }
+
 }