From 5900ed012908a1004158295daf9b8586c5f49653 Mon Sep 17 00:00:00 2001 From: ebruchez Date: Mon, 23 Sep 2019 10:09:38 -0700 Subject: [PATCH] For #4187: support separate custom LHHA modes --- .../oxf/xforms/control/ControlAjaxSupport.scala | 4 ++-- .../oxf/xforms/control/ControlLHHASupport.scala | 10 +++++----- .../xforms/control/XFormsComponentControl.scala | 15 +++------------ .../control/controls/XFormsTriggerControl.scala | 2 +- .../handlers/xhtml/XXFormsComponentHandler.scala | 11 ++++------- .../orbeon/oxf/xforms/xbl/AbstractBinding.scala | 14 ++++++++++++++ 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlAjaxSupport.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlAjaxSupport.scala index 5b85def812..71e2d5d57f 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlAjaxSupport.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlAjaxSupport.scala @@ -71,13 +71,13 @@ trait ControlAjaxSupport { } // Label, help, hint, alert - def addAjaxLHHA(attributesImpl: AttributesImpl, previousControlOpt: Option[XFormsControl]): Boolean = { + final def addAjaxLHHA(attributesImpl: AttributesImpl, previousControlOpt: Option[XFormsControl]): Boolean = { var added = false for { staticLhhaSupport ← staticControl.cast[StaticLHHASupport].toList // NOTE: `narrowTo` fails - lhha ← LHHA.values + lhha ← ajaxLhhaSupport // https://github.com/orbeon/orbeon-forms/issues/3836 // Q: Could we just check `isLocal` instead of `isForRepeat`? if staticLhhaSupport.hasLHHANotForRepeat(lhha) || staticLhhaSupport.hasLHHAPlaceholder(lhha) diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlLHHASupport.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlLHHASupport.scala index 519a6ba62a..8f7db1954d 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlLHHASupport.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/ControlLHHASupport.scala @@ -78,9 +78,9 @@ trait ControlLHHASupport { if (part.hasLHHA(prefixedId, lhha) && self.staticControl.isInstanceOf[StaticLHHASupport]) self match { case singleNodeControl: XFormsSingleNodeControl if lhha == LHHA.Alert ⇒ - new MutableAlertProperty(singleNodeControl, lhha, lhhaHTMLSupport(lhha)) + new MutableAlertProperty(singleNodeControl, lhha, htmlLhhaSupport(lhha)) case control: XFormsControl if lhha != LHHA.Alert ⇒ - new MutableLHHProperty(control, lhha, lhhaHTMLSupport(lhha)) + new MutableLHHProperty(control, lhha, htmlLhhaSupport(lhha)) case _ ⇒ NullLHHA } @@ -92,11 +92,11 @@ trait ControlLHHASupport { } } - // Whether we support HTML LHHA - def lhhaHTMLSupport: Set[LHHA] = LHHA.DefaultLHHAHTMLSupport + def htmlLhhaSupport: Set[LHHA] = LHHA.DefaultLHHAHTMLSupport + def ajaxLhhaSupport: Seq[LHHA] = LHHA.values def compareLHHA(other: XFormsControl) = - LHHA.values forall (lhha ⇒ lhhaProperty(lhha).value() == other.lhhaProperty(lhha).value()) + ajaxLhhaSupport forall (lhha ⇒ lhhaProperty(lhha).value() == other.lhhaProperty(lhha).value()) // Convenience accessors final def getLabel = lhhaProperty(LHHA.Label).value() diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/XFormsComponentControl.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/XFormsComponentControl.scala index 3b1ea407df..b944246696 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/XFormsComponentControl.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/XFormsComponentControl.scala @@ -18,7 +18,7 @@ import org.orbeon.oxf.util.CoreUtils._ import org.orbeon.oxf.util.XPath.FunctionContext import org.orbeon.oxf.xforms.BindingContext import org.orbeon.oxf.xforms.analysis.ElementAnalysis -import org.orbeon.oxf.xforms.analysis.controls.{ComponentControl, StaticLHHASupport, ValueComponentTrait, ViewTrait} +import org.orbeon.oxf.xforms.analysis.controls._ import org.orbeon.oxf.xforms.analysis.model.Instance import org.orbeon.oxf.xforms.control.controls.InstanceMirror._ import org.orbeon.oxf.xforms.control.controls.{InstanceMirror, XXFormsComponentRootControl, XXFormsDynamicControl} @@ -34,7 +34,6 @@ import org.orbeon.saxon.om.VirtualNode import org.orbeon.scaxon.Implicits.stringToStringValue import org.orbeon.scaxon.NodeConversions.unsafeUnwrapElement import org.w3c.dom.Node.ELEMENT_NODE -import org.xml.sax.helpers.AttributesImpl import scala.collection.JavaConverters._ @@ -493,14 +492,6 @@ class XFormsComponentControl( // Get the control at the root of the inner scope of the component def innerRootControl: XXFormsComponentRootControl = children collectFirst { case root: XXFormsComponentRootControl ⇒ root } get - private lazy val handleLHHA = - staticControl.abstractBinding.modeLHHA && ! staticControl.abstractBinding.modeLHHACustom - - // Don't add Ajax LHHA for custom-lhha mode - override def addAjaxLHHA(attributesImpl: AttributesImpl, previousControlOpt: Option[XFormsControl]): Boolean = - handleLHHA && super.addAjaxLHHA(attributesImpl, previousControlOpt) - - // Consider LHHA hasn't externally changed for custom-lhha mode - override def compareLHHA(other: XFormsControl): Boolean = - ! handleLHHA || super.compareLHHA(other) + override def ajaxLhhaSupport: Seq[LHHA] = staticControl.abstractBinding.standardLhhaAsSeq + override def htmlLhhaSupport: Set[LHHA] = staticControl.abstractBinding.standardLhhaAsSet } \ No newline at end of file diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/controls/XFormsTriggerControl.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/controls/XFormsTriggerControl.scala index bc9fca6ad1..c49b2d4f5f 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/controls/XFormsTriggerControl.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/control/controls/XFormsTriggerControl.scala @@ -29,7 +29,7 @@ class XFormsTriggerControl(container: XBLContainer, parent: XFormsControl, eleme import org.orbeon.oxf.xforms.control.controls.XFormsTriggerControl._ - override def lhhaHTMLSupport = TriggerLhhaHtmlSupport + override def htmlLhhaSupport = TriggerLhhaHtmlSupport // NOTE: We used to make the trigger non-relevant if it was static-readonly. But this caused issues: // diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/processor/handlers/xhtml/XXFormsComponentHandler.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/processor/handlers/xhtml/XXFormsComponentHandler.scala index dc2dc7d8e8..c63d9b9f1c 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/processor/handlers/xhtml/XXFormsComponentHandler.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/processor/handlers/xhtml/XXFormsComponentHandler.scala @@ -42,9 +42,6 @@ class XXFormsComponentHandler( protected override def getContainingElementQName = XMLUtils.buildQName(xformsHandlerContext.findXHTMLPrefix, staticControl.abstractBinding.containerElementName) - private lazy val modeIsLhhaButNotCustom = - staticControl.abstractBinding.modeLHHA && ! staticControl.abstractBinding.modeLHHACustom - protected override def addCustomClasses(classes: StringBuilder, control: XFormsControl): Unit = { if (classes.length != 0) classes.append(' ') @@ -69,7 +66,7 @@ class XXFormsComponentHandler( xformsHandlerContext.popComponentContext() protected override def handleLabel() = - if (modeIsLhhaButNotCustom) // also implied: label is local (from `XFormsControlLifecyleHandler`) + if (staticControl.abstractBinding.standardLhhaAsSet(LHHA.Label)) // also implied: label is local (from `XFormsControlLifecyleHandler`) handleLabelHintHelpAlert( lhhaAnalysis = getStaticLHHA(getPrefixedId, LHHA.Label), targetControlEffectiveId = getEffectiveId, @@ -80,9 +77,9 @@ class XXFormsComponentHandler( isExternal = false ) - protected override def handleAlert() = if (modeIsLhhaButNotCustom) super.handleAlert() - protected override def handleHint() = if (modeIsLhhaButNotCustom) super.handleHint() - protected override def handleHelp() = if (modeIsLhhaButNotCustom) super.handleHelp() + protected override def handleAlert() = if (staticControl.abstractBinding.standardLhhaAsSet(LHHA.Alert)) super.handleAlert() + protected override def handleHint() = if (staticControl.abstractBinding.standardLhhaAsSet(LHHA.Hint)) super.handleHint() + protected override def handleHelp() = if (staticControl.abstractBinding.standardLhhaAsSet(LHHA.Help)) super.handleHelp() // If there is a label-for, use that, otherwise don't use @for as we are not pointing to an HTML form control // NOTE: Used by `handleLabel()` if there is a local LHHA, and by `findTargetControlForEffectiveId`. diff --git a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/xbl/AbstractBinding.scala b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/xbl/AbstractBinding.scala index fd013fc716..a6d0240fd7 100644 --- a/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/xbl/AbstractBinding.scala +++ b/xforms/jvm/src/main/scala/org/orbeon/oxf/xforms/xbl/AbstractBinding.scala @@ -24,6 +24,7 @@ import org.orbeon.oxf.util.PipelineUtils import org.orbeon.oxf.xforms.XFormsConstants._ import org.orbeon.oxf.xforms._ import org.orbeon.oxf.xforms.analysis.ElementAnalysis.attSet +import org.orbeon.oxf.xforms.analysis.controls.LHHA import org.orbeon.oxf.xforms.analysis.model.ThrowawayInstance import org.orbeon.oxf.xforms.event.XFormsEvents._ import org.orbeon.oxf.xforms.xbl.XBLAssets.HeadElement @@ -82,6 +83,19 @@ case class AbstractBinding( val modeSelection = xblMode("selection") // to indicate that the control acts as a selection control val modeHandlers = ! xblMode("nohandlers") + val modeIsLhhaButNotCustom = modeLHHA && ! modeLHHACustom + + // LHHA that are handled the standard way (as opposed to the "custom" way) + val standardLhhaAsSeq: Seq[LHHA] = LHHA.values flatMap { lhha ⇒ + ! ( + modeLHHACustom && ! xblMode(s"-custom-${lhha.entryName}") || + modeLHHA && xblMode(s"+custom-${lhha.entryName}") + ) option + lhha + } + + val standardLhhaAsSet: Set[LHHA] = standardLhhaAsSeq.to[Set] + val labelFor : Option[String] = bindingElement.attributeValueOpt(XXBL_LABEL_FOR_QNAME) val formatOpt : Option[String] = bindingElement.attributeValueOpt(XXBL_FORMAT_QNAME) val serializeExternalValueOpt : Option[String] = bindingElement.attributeValueOpt(XXBL_SERIALIZE_EXTERNAL_VALUE_QNAME)