You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2014/05/08 09:13:51 UTC
[05/10] git commit: ISIS-764: moving functionality into ReferencePanel
ISIS-764: moving functionality into ReferencePanel
... from EntityLinkSelect2Panel.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/bf6b900b
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/bf6b900b
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/bf6b900b
Branch: refs/heads/ISIS-764
Commit: bf6b900b3110992dd9acf9c31369f1d02790c0bf
Parents: a8eee7a
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed May 7 23:50:56 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed May 7 23:50:56 2014 +0100
----------------------------------------------------------------------
.../reference/EntityLinkSelect2Panel.java | 361 +------------------
.../scalars/reference/ReferencePanel.html | 3 +-
.../scalars/reference/ReferencePanel.java | 288 ++++++++++++++-
.../ObjectAdapterMementoProviderAbstract.java | 4 +
4 files changed, 299 insertions(+), 357 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/bf6b900b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/EntityLinkSelect2Panel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/EntityLinkSelect2Panel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/EntityLinkSelect2Panel.java
index 33d78b7..62ed565 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/EntityLinkSelect2Panel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/EntityLinkSelect2Panel.java
@@ -19,76 +19,37 @@
package org.apache.isis.viewer.wicket.ui.components.scalars.reference;
-import java.util.List;
-
-import com.google.common.collect.Lists;
-import com.vaynberg.wicket.select2.ChoiceProvider;
import com.vaynberg.wicket.select2.Select2Choice;
-import com.vaynberg.wicket.select2.Select2MultiChoice;
-import com.vaynberg.wicket.select2.Settings;
-import org.apache.wicket.Component;
-import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.html.form.FormComponentPanel;
-import org.apache.wicket.markup.html.link.Link;
-import org.apache.wicket.model.IModel;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
-import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.model.models.ActionModel;
-import org.apache.isis.viewer.wicket.model.models.EntityModel;
-import org.apache.isis.viewer.wicket.model.models.EntityModel.RenderingHint;
-import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending;
-import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending.Util;
-import org.apache.isis.viewer.wicket.model.util.MementoFunctions;
-import org.apache.isis.viewer.wicket.ui.ComponentFactory;
-import org.apache.isis.viewer.wicket.ui.ComponentType;
import org.apache.isis.viewer.wicket.ui.components.actions.ActionInvokeHandler;
-import org.apache.isis.viewer.wicket.ui.components.actions.ActionParametersFormPanel;
-import org.apache.isis.viewer.wicket.ui.components.widgets.ObjectAdapterMementoProviderAbstract;
-import org.apache.isis.viewer.wicket.ui.components.widgets.Select2ChoiceUtil;
import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired;
import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.FormComponentPanelAbstract;
-import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
/**
* {@link FormComponentPanel} representing a reference to an entity: a link and
* (optionally) an autocomplete field.
*/
-public class EntityLinkSelect2Panel extends FormComponentPanelAbstract<ObjectAdapter> implements CancelHintRequired, ActionInvokeHandler {
+class EntityLinkSelect2Panel extends FormComponentPanelAbstract<ObjectAdapter> implements CancelHintRequired, ActionInvokeHandler {
private static final long serialVersionUID = 1L;
- private static final String ID_AUTO_COMPLETE = "autoComplete";
- private static final String ID_ENTITY_ICON_AND_TITLE = "entityIconAndTitle";
-
/**
* This component may be null if there are no choices or autoComplete, or if in read-only mode.
*/
- private Select2Choice<ObjectAdapterMemento> select2Field;
- private Link<String> entityDetailsLink;
- private Link<String> entityClearLink;
+ Select2Choice<ObjectAdapterMemento> select2Field;
- public EntityLinkSelect2Panel(final String id, final ScalarModel scalarModel) {
- super(id, scalarModel);
- setType(ObjectAdapter.class);
- buildGui();
- }
+ ReferencePanel owningPanel;
- public ScalarModel getScalarModel() {
- return (ScalarModel) getModel();
- }
-
- /**
- * Builds the parts of the GUI that are not dynamic.
- */
- private void buildGui() {
+ public EntityLinkSelect2Panel(final String id, final ReferencePanel owningPanel) {
+ super(id, owningPanel.getModel());
+ this.owningPanel = owningPanel;
+
+ setType(ObjectAdapter.class);
syncWithInput();
}
@@ -104,54 +65,6 @@ public class EntityLinkSelect2Panel extends FormComponentPanelAbstract<ObjectAda
return super.checkRequired();
}
- @Override
- public boolean isRequired() {
- return super.isRequired();
- }
-
-
- /**
- * Must be called after {@link #setEnabled(boolean)} to ensure that the
- * <tt>findUsing</tt> button, and the <tt>entityClearLink</tt> are
- * shown/not shown as required.
- *
- * <p>
- * REVIEW: there ought to be a better way to do this. I'd hoped to override
- * {@link #setEnabled(boolean)}, but it is <tt>final</tt>, and there doesn't
- * seem to be anyway to install a listener. One option might be to move it
- * to {@link #onBeforeRender()} ?
- */
- public void syncVisibilityAndUsability() {
-
- final boolean mutability = isEnableAllowed() && !getScalarModel().isViewMode();
-
- if(entityClearLink != null) {
- entityClearLink.setVisible(mutability);
- }
-
- if(entityDetailsLink != null) {
- entityDetailsLink.setVisible(getScalarModel().getRenderingHint() == RenderingHint.REGULAR);
- }
-
- if(select2Field != null) {
- select2Field.setEnabled(mutability);
- }
-
- if(isEditableWithEitherAutoCompleteOrChoices()) {
- permanentlyHide(ID_ENTITY_ICON_AND_TITLE);
- }
- }
-
- protected void doSyncVisibilityAndUsability(boolean mutability) {
- if(select2Field != null) {
- select2Field.setEnabled(mutability);
- }
-
- if(isEditableWithEitherAutoCompleteOrChoices()) {
- permanentlyHide(ID_ENTITY_ICON_AND_TITLE);
- }
- }
-
/**
* Since we override {@link #convertInput()}, it is (apparently) enough to
* just return a value that is suitable for error reporting.
@@ -160,23 +73,15 @@ public class EntityLinkSelect2Panel extends FormComponentPanelAbstract<ObjectAda
*/
@Override
public String getInput() {
- final ObjectAdapter pendingElseCurrentAdapter = getScalarModel().getPendingElseCurrentAdapter();
+ final ObjectAdapter pendingElseCurrentAdapter = owningPanel.getModel().getPendingElseCurrentAdapter();
return pendingElseCurrentAdapter != null? pendingElseCurrentAdapter.titleString(null): "(no object)";
}
@Override
protected void convertInput() {
-
- if(getScalarModel().isEditMode() && isEditableWithEitherAutoCompleteOrChoices()) {
- // flush changes to pending
- onSelected(select2Field.getConvertedInput());
- }
-
- final ObjectAdapter pendingAdapter = getScalarModel().getPendingAdapter();
- setConvertedInput(pendingAdapter);
+ this.owningPanel.convertInput(this);
}
-
@Override
protected void onBeforeRender() {
syncWithInput();
@@ -184,258 +89,16 @@ public class EntityLinkSelect2Panel extends FormComponentPanelAbstract<ObjectAda
}
private void syncWithInput() {
- final ObjectAdapter adapter = getPendingElseCurrentAdapter();
-
- syncLinkWithInput(adapter);
- doSyncWithInputIfAutoCompleteOrChoices();
- syncVisibilityAndUsability();
- }
-
- private void doSyncWithInputIfAutoCompleteOrChoices() {
-
- if(!isEditableWithEitherAutoCompleteOrChoices()) {
- // this is horrid; adds a label to the id
- // should instead be a 'temporary hide'
- permanentlyHide(ID_AUTO_COMPLETE);
- select2Field = null; // this forces recreation next time around
- return;
- }
-
- final IModel<ObjectAdapterMemento> model = ScalarModelWithPending.Util.createModel(getScalarModel().asScalarModelWithPending());
-
- if(select2Field == null) {
- setRequired(getScalarModel().isRequired());
- select2Field = Select2ChoiceUtil.newSelect2Choice(ID_AUTO_COMPLETE, model, getScalarModel());
- setProviderAndCurrAndPending(select2Field, getScalarModel().getActionArgsHint());
- if(!getScalarModel().hasChoices()) {
- final Settings settings = select2Field.getSettings();
- ScalarModel scalarModel = getScalarModel();
- final int minLength = scalarModel.getAutoCompleteMinLength();
- settings.setMinimumInputLength(minLength);
- settings.setPlaceholder(scalarModel.getName());
- }
- addOrReplace(select2Field);
- } else {
- //
- // the select2Field already exists, so the widget has been rendered before. If it is
- // being re-rendered now, it may be because some other property/parameter was invalid.
- // when the form was submitted, the selected object (its oid as a string) would have
- // been saved as rawInput. If the property/parameter had been valid, then this rawInput
- // would be correctly converted and processed by the select2Field's choiceProvider. However,
- // an invalid property/parameter means that the webpage is re-rendered in another request,
- // and the rawInput can no longer be interpreted. The net result is that the field appears
- // with no input.
- //
- // The fix is therefore (I think) simply to clear any rawInput, so that the select2Field
- // renders its state from its model.
- //
- // see: FormComponent#getInputAsArray()
- // see: Select2Choice#renderInitializationScript()
- //
- select2Field.clearInput();
- }
-
-
- // no need for link, since can see in drop-down
- permanentlyHide(ID_ENTITY_ICON_AND_TITLE);
-
- // no need for the 'null' title, since if there is no object yet
- // can represent this fact in the drop-down
- // permanentlyHide(ID_ENTITY_TITLE_NULL);
- }
-
-
- private ChoiceProvider<ObjectAdapterMemento> providerForObjectAutoComplete() {
- final EntityModel entityModel = getScalarModel();
- return new ObjectAdapterMementoProviderAbstract(getScalarModel()) {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected List<ObjectAdapterMemento> obtainMementos(String term) {
- final ObjectSpecification typeOfSpecification = entityModel.getTypeOfSpecification();
- final AutoCompleteFacet autoCompleteFacet = typeOfSpecification.getFacet(AutoCompleteFacet.class);
- final List<ObjectAdapter> results = autoCompleteFacet.execute(term);
- return Lists.transform(results, ObjectAdapterMemento.Functions.fromAdapter());
- }
-
- };
- }
-
- private ChoiceProvider<ObjectAdapterMemento> providerForParamOrPropertyAutoComplete() {
- final EntityModel entityModel = getScalarModel();
- return new ObjectAdapterMementoProviderAbstract(getScalarModel()) {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected List<ObjectAdapterMemento> obtainMementos(String term) {
- final List<ObjectAdapter> autoCompleteChoices = Lists.newArrayList();
- final ScalarModel scalarModel = (ScalarModel) entityModel;
- if(scalarModel.hasAutoComplete()) {
- autoCompleteChoices.addAll(scalarModel.getAutoComplete(term));
- }
- // take a copy otherwise is only lazily evaluated
- return Lists.newArrayList(Lists.transform(autoCompleteChoices, ObjectAdapterMemento.Functions.fromAdapter()));
- }
-
- };
- }
-
- private List<ObjectAdapterMemento> getChoiceMementos(final ObjectAdapter[] argsIfAvailable) {
-
- final List<ObjectAdapter> choices = Lists.newArrayList();
- final ScalarModel scalarModel = (ScalarModel) getScalarModel();;
- if(scalarModel.hasChoices()) {
- choices.addAll(scalarModel.getChoices(argsIfAvailable));
- }
- // take a copy otherwise is only lazily evaluated
- return Lists.newArrayList(Lists.transform(choices, MementoFunctions.fromAdapter()));
- }
-
- private void syncLinkWithInput(final ObjectAdapter adapter) {
- if (adapter != null) {
- addOrReplaceIconAndTitle(adapter);
- } else {
- permanentlyHide(ID_ENTITY_ICON_AND_TITLE);
- }
- }
-
-
- private void addOrReplaceIconAndTitle(ObjectAdapter pendingOrCurrentAdapter) {
- final EntityModel entityModelForLink = new EntityModel(pendingOrCurrentAdapter);
- entityModelForLink.setContextAdapterIfAny(getScalarModel().getContextAdapterIfAny());
- entityModelForLink.setRenderingHint(getScalarModel().getRenderingHint());
- final ComponentFactory componentFactory = getComponentFactoryRegistry().findComponentFactory(ComponentType.ENTITY_ICON_AND_TITLE, entityModelForLink);
- final Component component = componentFactory.createComponent(entityModelForLink);
- addOrReplace(component);
+ this.owningPanel.syncWithInput(this);
}
-
@Override
public void onClick(final ActionModel actionModel) {
}
- public void onSelected(final ObjectAdapterMemento selectedAdapterMemento) {
- getScalarModel().setPending(selectedAdapterMemento);
- getScalarModel().setObject(selectedAdapterMemento!=null?selectedAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK):null);
- if(this.select2Field != null) {
- select2Field.getModel().setObject(selectedAdapterMemento);
- }
- // not sure why this was here, at any rate it trips up when performing validation with modal dialogs.
- // renderSamePage();
- }
-
- public void onNoResults() {
- renderSamePage();
- }
-
@Override
public void onCancel() {
- getScalarModel().clearPending();
- }
-
- private ObjectAdapter getPendingElseCurrentAdapter() {
- return getScalarModel().getPendingElseCurrentAdapter();
- }
-
- private void renderSamePage() {
- setResponsePage(getPage());
- }
-
- private boolean isEditableWithEitherAutoCompleteOrChoices() {
- // never doesn't apply in compact rendering contexts (ie tables)
- if(getScalarModel().getRenderingHint().isInTable()) {
- return false;
- }
- // doesn't apply if not editable, either
- if(getScalarModel().isViewMode()) {
- return false;
- }
- return getScalarModel().hasChoices() || hasParamOrPropertyAutoComplete() || hasObjectAutoComplete();
- }
-
- private boolean hasParamOrPropertyAutoComplete() {
- return getScalarModel().hasAutoComplete();
- }
-
- private boolean hasObjectAutoComplete() {
-
- // on property/param
- boolean hasAutoComplete = getScalarModel().hasAutoComplete();
- if(hasAutoComplete) {
- return true;
- }
-
- // else on underlying type
- final ObjectSpecification typeOfSpecification = getScalarModel().getTypeOfSpecification();
- final AutoCompleteFacet autoCompleteFacet =
- (typeOfSpecification != null)? typeOfSpecification.getFacet(AutoCompleteFacet.class):null;
- return autoCompleteFacet != null;
- }
-
- // //////////////////////////////////////
-
- public void addFormComponentBehavior(Behavior behavior) {
- if(select2Field != null) {
- select2Field.add(behavior);
- }
- }
-
- public boolean updateChoices(ObjectAdapter[] argsIfAvailable) {
- if(select2Field != null) {
- setProviderAndCurrAndPending(select2Field, argsIfAvailable);
- return true;
- } else {
- return false;
- }
- }
-
- private void setProviderAndCurrAndPending(
- final Select2Choice<ObjectAdapterMemento> select2Field,
- final ObjectAdapter[] argsIfAvailable) {
-
- if (getScalarModel().hasChoices()) {
- final List<ObjectAdapterMemento> choiceMementos = getChoiceMementos(argsIfAvailable);
- select2Field.setProvider(providerForChoices(choiceMementos));
- getScalarModel().clearPending();
- resetIfCurrentNotInChoices(select2Field, choiceMementos);
- } else if(hasParamOrPropertyAutoComplete()) {
- select2Field.setProvider(providerForParamOrPropertyAutoComplete());
- getScalarModel().clearPending();
- } else {
- select2Field.setProvider(providerForObjectAutoComplete());
- getScalarModel().clearPending();
- }
- }
-
- private ObjectAdapterMementoProviderAbstract providerForChoices(final List<ObjectAdapterMemento> choiceMementos) {
- return new ObjectAdapterMementoProviderAbstract(getScalarModel()) {
- private static final long serialVersionUID = 1L;
- @Override
- protected List<ObjectAdapterMemento> obtainMementos(String unused) {
- return choiceMementos;
- }
- };
- }
-
- private void resetIfCurrentNotInChoices(final Select2Choice<ObjectAdapterMemento> select2Field, final List<ObjectAdapterMemento> choiceMementos) {
- final ObjectAdapterMemento curr = select2Field.getModelObject();
- if(curr == null) {
- select2Field.getModel().setObject(null);
- getModel().setObject(null);
- return;
- }
- if(!curr.containedIn(choiceMementos)) {
- if(!choiceMementos.isEmpty()) {
- final ObjectAdapterMemento newAdapterMemento = choiceMementos.get(0);
- select2Field.getModel().setObject(newAdapterMemento);
- getModel().setObject(newAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK));
- } else {
- select2Field.getModel().setObject(null);
- getModel().setObject(null);
- }
- }
+ owningPanel.getModel().clearPending();
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/bf6b900b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.html
index 6d39871..dd9de09 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.html
@@ -33,8 +33,7 @@
<div class="entityLinkSelect2Panel entityLinkComponentType">
<div class="wrapper">
<span class="autoCompletePlaceholder">
- <span wicket:id="entityLink">
- </span>
+ <span wicket:id="entityLink">link or drop down</span>
</span>
<div class="clear"/>
</div>
http://git-wip-us.apache.org/repos/asf/isis/blob/bf6b900b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
index 8909687..df28aea 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
@@ -19,22 +19,40 @@
package org.apache.isis.viewer.wicket.ui.components.scalars.reference;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import com.vaynberg.wicket.select2.ChoiceProvider;
+import com.vaynberg.wicket.select2.Select2Choice;
+import com.vaynberg.wicket.select2.Settings;
+
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.FormComponentLabel;
+import org.apache.wicket.model.IModel;
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.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending;
+import org.apache.isis.viewer.wicket.model.models.ScalarModelWithPending.Util;
+import org.apache.isis.viewer.wicket.ui.ComponentFactory;
import org.apache.isis.viewer.wicket.ui.ComponentType;
import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract;
+import org.apache.isis.viewer.wicket.ui.components.widgets.ObjectAdapterMementoProviderAbstract;
+import org.apache.isis.viewer.wicket.ui.components.widgets.Select2ChoiceUtil;
import org.apache.isis.viewer.wicket.ui.components.widgets.entitysimplelink.EntityLinkSimplePanel;
+import org.apache.isis.viewer.wicket.ui.util.Components;
import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
/**
@@ -50,6 +68,9 @@ public class ReferencePanel extends ScalarPanelAbstract {
private static final String ID_SCALAR_IF_COMPACT = "scalarIfCompact";
+ static final String ID_AUTO_COMPLETE = "autoComplete";
+ static final String ID_ENTITY_ICON_AND_TITLE = "entityIconAndTitle";
+
private EntityLinkSelect2Panel entityLink;
private EntityLinkSimplePanel entitySimpleLink;
@@ -61,14 +82,14 @@ public class ReferencePanel extends ScalarPanelAbstract {
protected void onBeforeRenderWhenEnabled() {
super.onBeforeRenderWhenEnabled();
entityLink.setEnabled(true);
- entityLink.syncVisibilityAndUsability();
+ entityLink.owningPanel.syncVisibilityAndUsability(entityLink, entityLink.select2Field);
}
@Override
protected void onBeforeRenderWhenViewMode() {
super.onBeforeRenderWhenViewMode();
entityLink.setEnabled(true);
- entityLink.syncVisibilityAndUsability();
+ entityLink.owningPanel.syncVisibilityAndUsability(entityLink, entityLink.select2Field);
}
@Override
@@ -77,7 +98,7 @@ public class ReferencePanel extends ScalarPanelAbstract {
final EntityModel entityLinkModel = (EntityModel) entityLink.getModel();
entityLinkModel.toViewMode();
setTitleAttribute(disableReason);
- entityLink.syncVisibilityAndUsability();
+ entityLink.owningPanel.syncVisibilityAndUsability(entityLink, entityLink.select2Field);
}
private void setTitleAttribute(final String titleAttribute) {
@@ -89,7 +110,7 @@ public class ReferencePanel extends ScalarPanelAbstract {
final ScalarModel scalarModel = getModel();
final String name = scalarModel.getName();
- entityLink = new EntityLinkSelect2Panel(ComponentType.ENTITY_LINK.getWicketId(), getModel());
+ entityLink = new EntityLinkSelect2Panel(ComponentType.ENTITY_LINK.getWicketId(), this);
setOutputMarkupId(true);
entityLink.setOutputMarkupId(true);
@@ -182,12 +203,267 @@ public class ReferencePanel extends ScalarPanelAbstract {
@Override
protected void addFormComponentBehavior(Behavior behavior) {
- entityLink.addFormComponentBehavior(behavior);
+ if(entityLink.select2Field != null) {
+ entityLink.select2Field.add(behavior);
+ }
}
@Override
public boolean updateChoices(ObjectAdapter[] argsIfAvailable) {
- return entityLink.updateChoices(argsIfAvailable);
+ if(entityLink.select2Field != null) {
+ setProviderAndCurrAndPending(entityLink.select2Field, argsIfAvailable);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // //////////////////////////////////////
+
+
+ boolean isEditableWithEitherAutoCompleteOrChoices() {
+ if(getModel().getRenderingHint().isInTable()) {
+ return false;
+ }
+ // doesn't apply if not editable, either
+ if(getModel().isViewMode()) {
+ return false;
+ }
+ return getModel().hasChoices() || hasParamOrPropertyAutoComplete() || hasObjectAutoComplete();
}
+ boolean hasParamOrPropertyAutoComplete() {
+ return getModel().hasAutoComplete();
+ }
+
+ boolean hasObjectAutoComplete() {
+ boolean hasAutoComplete = getModel().hasAutoComplete();
+ if(hasAutoComplete) {
+ return true;
+ }
+
+ // else on underlying type
+ final ObjectSpecification typeOfSpecification = getModel().getTypeOfSpecification();
+ final AutoCompleteFacet autoCompleteFacet =
+ (typeOfSpecification != null)? typeOfSpecification.getFacet(AutoCompleteFacet.class):null;
+ return autoCompleteFacet != null;
+ }
+
+ void setProviderAndCurrAndPending(final Select2Choice<ObjectAdapterMemento> select2Field, final ObjectAdapter[] argsIfAvailable) {
+ if (getModel().hasChoices()) {
+
+ final List<ObjectAdapterMemento> choiceMementos = getChoiceMementos(argsIfAvailable);
+ ObjectAdapterMementoProviderAbstract providerForChoices = providerForChoices(choiceMementos);
+
+ select2Field.setProvider(providerForChoices);
+ getModel().clearPending();
+
+ resetIfCurrentNotInChoices(select2Field, choiceMementos);
+
+ } else if(hasParamOrPropertyAutoComplete()) {
+ select2Field.setProvider(providerForParamOrPropertyAutoComplete());
+ getModel().clearPending();
+ } else {
+ select2Field.setProvider(providerForObjectAutoComplete());
+ getModel().clearPending();
+ }
+ }
+
+ List<ObjectAdapterMemento> getChoiceMementos(final ObjectAdapter[] argsIfAvailable) {
+ final List<ObjectAdapter> choices = Lists.newArrayList();
+ if(getModel().hasChoices()) {
+ choices.addAll(getModel().getChoices(argsIfAvailable));
+ }
+ // take a copy otherwise is only lazily evaluated
+ return Lists.newArrayList(Lists.transform(choices, ObjectAdapterMemento.Functions.fromAdapter()));
+ }
+
+
+ ChoiceProvider<ObjectAdapterMemento> providerForObjectAutoComplete() {
+ return new ObjectAdapterMementoProviderAbstract(getModel()) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected List<ObjectAdapterMemento> obtainMementos(String term) {
+ final ObjectSpecification typeOfSpecification = getScalarModel().getTypeOfSpecification();
+ final AutoCompleteFacet autoCompleteFacet = typeOfSpecification.getFacet(AutoCompleteFacet.class);
+ final List<ObjectAdapter> results = autoCompleteFacet.execute(term);
+ return Lists.transform(results, ObjectAdapterMemento.Functions.fromAdapter());
+ }
+ };
+ }
+
+
+ ChoiceProvider<ObjectAdapterMemento> providerForParamOrPropertyAutoComplete() {
+ return new ObjectAdapterMementoProviderAbstract(getModel()) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected List<ObjectAdapterMemento> obtainMementos(String term) {
+ final List<ObjectAdapter> autoCompleteChoices = Lists.newArrayList();
+ if(getScalarModel().hasAutoComplete()) {
+ autoCompleteChoices.addAll(getScalarModel().getAutoComplete(term));
+ }
+ // take a copy otherwise is only lazily evaluated
+ return Lists.newArrayList(Lists.transform(autoCompleteChoices, ObjectAdapterMemento.Functions.fromAdapter()));
+ }
+
+ };
+ }
+
+
+ void resetIfCurrentNotInChoices(final Select2Choice<ObjectAdapterMemento> select2Field, final List<ObjectAdapterMemento> choiceMementos) {
+ final ObjectAdapterMemento curr = select2Field.getModelObject();
+ if(curr == null) {
+ select2Field.getModel().setObject(null);
+ this.getModel().setObject(null);
+ return;
+ }
+ if(!curr.containedIn(choiceMementos)) {
+ if(!choiceMementos.isEmpty()) {
+ final ObjectAdapterMemento newAdapterMemento = choiceMementos.get(0);
+ select2Field.getModel().setObject(newAdapterMemento);
+ this.getModel().setObject(newAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK));
+ } else {
+ select2Field.getModel().setObject(null);
+ this.getModel().setObject(null);
+ }
+ }
+ }
+
+ ObjectAdapterMementoProviderAbstract providerForChoices(final List<ObjectAdapterMemento> choiceMementos) {
+ return new ObjectAdapterMementoProviderAbstract(getModel()) {
+ private static final long serialVersionUID = 1L;
+ @Override
+ protected List<ObjectAdapterMemento> obtainMementos(String unused) {
+ return choiceMementos;
+ }
+ };
+ }
+
+ void syncLinkWithInput(EntityLinkSelect2Panel linkPanel, final ObjectAdapter adapter) {
+ if (adapter != null) {
+ addOrReplaceIconAndTitle(linkPanel, adapter);
+ } else {
+ Components.permanentlyHide(linkPanel, ReferencePanel.ID_ENTITY_ICON_AND_TITLE);
+ }
+ }
+
+ void addOrReplaceIconAndTitle(EntityLinkSelect2Panel linkPanel, ObjectAdapter pendingOrCurrentAdapter) {
+
+ final EntityModel entityModelForLink = new EntityModel(pendingOrCurrentAdapter);
+
+ entityModelForLink.setContextAdapterIfAny(getModel().getContextAdapterIfAny());
+ entityModelForLink.setRenderingHint(getModel().getRenderingHint());
+
+ final ComponentFactory componentFactory = getComponentFactoryRegistry().findComponentFactory(ComponentType.ENTITY_ICON_AND_TITLE, entityModelForLink);
+ final Component component = componentFactory.createComponent(entityModelForLink);
+
+ linkPanel.addOrReplace(component);
+ }
+
+
+ void onSelected(EntityLinkSelect2Panel linkPanel, final ObjectAdapterMemento selectedAdapterMemento) {
+
+ getModel().setPending(selectedAdapterMemento);
+ getModel().setObject(selectedAdapterMemento!=null?selectedAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK):null);
+ if(linkPanel.select2Field != null) {
+ linkPanel.select2Field.getModel().setObject(selectedAdapterMemento);
+ }
+ }
+
+ /**
+ * Must be called after {@link #setEnabled(boolean)}, apparently...
+ * originally to ensure that the findUsing button and entityClearLink were
+ * shown/not shown as required, however these have now gone. Which beckons the question,
+ * is it still important?
+ *
+ * <p>
+ * REVIEW: there ought to be a better way to do this. I'd hoped to override
+ * {@link #setEnabled(boolean)}, but it is <tt>final</tt>, and there doesn't
+ * seem to be anyway to install a listener. One option might be to move it
+ * to {@link #onBeforeRender()} ?
+ */
+ void syncVisibilityAndUsability(EntityLinkSelect2Panel linkPanel, Select2Choice<ObjectAdapterMemento> select2Field) {
+ final boolean mutability = linkPanel.isEnableAllowed() && !getModel().isViewMode();
+
+ if(select2Field != null) {
+ select2Field.setEnabled(mutability);
+ }
+
+ if(isEditableWithEitherAutoCompleteOrChoices()) {
+ Components.permanentlyHide(linkPanel, ReferencePanel.ID_ENTITY_ICON_AND_TITLE);
+ }
+ }
+
+ void convertInput(EntityLinkSelect2Panel linkPanel) {
+ if(getModel().isEditMode() && isEditableWithEitherAutoCompleteOrChoices()) {
+ // flush changes to pending
+ this.onSelected(linkPanel, linkPanel.select2Field.getConvertedInput());
+ }
+
+ final ObjectAdapter pendingAdapter = getModel().getPendingAdapter();
+ linkPanel.setConvertedInput(pendingAdapter);
+ }
+
+ void syncWithInput(EntityLinkSelect2Panel linkPanel) {
+ final ObjectAdapter adapter = getModel().getPendingElseCurrentAdapter();
+ syncLinkWithInput(linkPanel, adapter);
+ doSyncWithInputIfAutoCompleteOrChoices(linkPanel);
+ syncVisibilityAndUsability(linkPanel, linkPanel.select2Field);
+ }
+
+ void doSyncWithInputIfAutoCompleteOrChoices(EntityLinkSelect2Panel linkPanel) {
+ if(!isEditableWithEitherAutoCompleteOrChoices()) {
+ // this is horrid; adds a label to the id
+ // should instead be a 'temporary hide'
+ Components.permanentlyHide(linkPanel, ReferencePanel.ID_AUTO_COMPLETE);
+ linkPanel.select2Field = null; // this forces recreation next time around
+ return;
+ }
+
+ final IModel<ObjectAdapterMemento> model = Util.createModel(getModel().asScalarModelWithPending());
+
+ if(linkPanel.select2Field == null) {
+ linkPanel.setRequired(getModel().isRequired());
+ linkPanel.select2Field = Select2ChoiceUtil.newSelect2Choice(ReferencePanel.ID_AUTO_COMPLETE, model, getModel());
+ setProviderAndCurrAndPending(linkPanel.select2Field, getModel().getActionArgsHint());
+ if(!getModel().hasChoices()) {
+ final Settings settings = linkPanel.select2Field.getSettings();
+ final int minLength = getModel().getAutoCompleteMinLength();
+ settings.setMinimumInputLength(minLength);
+ settings.setPlaceholder(getModel().getName());
+ }
+ linkPanel.addOrReplace(linkPanel.select2Field);
+ } else {
+ //
+ // the select2Field already exists, so the widget has been rendered before. If it is
+ // being re-rendered now, it may be because some other property/parameter was invalid.
+ // when the form was submitted, the selected object (its oid as a string) would have
+ // been saved as rawInput. If the property/parameter had been valid, then this rawInput
+ // would be correctly converted and processed by the select2Field's choiceProvider. However,
+ // an invalid property/parameter means that the webpage is re-rendered in another request,
+ // and the rawInput can no longer be interpreted. The net result is that the field appears
+ // with no input.
+ //
+ // The fix is therefore (I think) simply to clear any rawInput, so that the select2Field
+ // renders its state from its model.
+ //
+ // see: FormComponent#getInputAsArray()
+ // see: Select2Choice#renderInitializationScript()
+ //
+ linkPanel.select2Field.clearInput();
+ }
+
+ // no need for link, since can see in drop-down
+ Components.permanentlyHide(linkPanel, ReferencePanel.ID_ENTITY_ICON_AND_TITLE);
+
+ // no need for the 'null' title, since if there is no object yet
+ // can represent this fact in the drop-down
+ // permanentlyHide(ID_ENTITY_TITLE_NULL);
+ }
+
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/bf6b900b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/ObjectAdapterMementoProviderAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/ObjectAdapterMementoProviderAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/ObjectAdapterMementoProviderAbstract.java
index a55a20f..fd4a4d4 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/ObjectAdapterMementoProviderAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/ObjectAdapterMementoProviderAbstract.java
@@ -80,4 +80,8 @@ public abstract class ObjectAdapterMementoProviderAbstract extends TextChoicePro
};
return Collections2.transform(ids, function);
}
+
+ protected ScalarModel getScalarModel() {
+ return scalarModel;
+ }
}
\ No newline at end of file