You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/07/25 15:09:55 UTC
svn commit: r679791 - in
/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components:
./ ModalFlow.java ModalFlowTag.java
Author: skitching
Date: Fri Jul 25 06:09:54 2008
New Revision: 679791
URL: http://svn.apache.org/viewvc?rev=679791&view=rev
Log:
Add components to support starting a called flow in a modal popup window.
Added:
myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/
myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java (with props)
myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java (with props)
Added: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java?rev=679791&view=auto
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java (added)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java Fri Jul 25 06:09:54 2008
@@ -0,0 +1,232 @@
+/*
+ * 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.myfaces.orchestra.flow.components;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+/**
+ * A component which allows an Orchestra Flow to be rendered into a popup window embedded
+ * in the page that calls the flow.
+ * <p>
+ * When this component is present in a page, and a postback of the page triggers
+ * navigation to the entry point of a flow, then instead of actually navigating to
+ * the flow entry page the current page is re-rendered. This component will then
+ * take care of rendering appropriate javascript to open the popup window and load
+ * the flow entry page into it.
+ * <p>
+ * This component does not implement a "modal dialog" itself; it assumes that some other
+ * library is used to actually manage the dialog (eg the s:modalDialog component from
+ * the Tomahawk Sandbox). Instead, the page author is responsible for placing a hidden
+ * modal dialog component in the page, and then configuring this component with an
+ * appropriate javascript command to execute when a flow begins. This
+ * component then renders that javascript only in the right circumstances.
+ * <p>
+ * This component has no effect at all on navigation that is not a "flow call".
+ * <p>
+ * Note that triggering a flow is always done via a normal postback of the calling
+ * page, just as it happens for a non-modal flow call. This keeps things consistent.
+ * When using flow.xml files for configuration, the decision on whether a particular
+ * navigation is a flow call or not is done only in the flow.xml file, and not in the
+ * page. But whether a flow (if one is triggered) is normal or modal is made only in
+ * the page, and not in the flow.xml files. There is no overlap in responsibility
+ * here, ie no place where configuration must be consistent in two different places
+ * in order for the system to work. Whether a navigation is to a flow is a programmer
+ * decision; whether it is a popup or not is a UI designer decision and keeping these
+ * separated is important.
+ * <p>
+ * The alternative of popping up a window then posting from that is not used because
+ * that would mean that the page is making assumptions about whether a flow call is
+ * going to happen or not; it couples the page and the flow behaviour too tightly.
+ * If the postback did *not* trigger the start of a flow for example, then things
+ * would get very confusing.
+ * <p>
+ * This design should be fully compatible with AJAX; an AJAX postback can trigger
+ * a flow on the server. As long as the page "updated region" includes this modalFlow
+ * component, and the javascript returned to the browser in that region is executed
+ * then a popup modal flow should also work fine.
+ */
+public class ModalFlow extends UIComponentBase
+{
+ public static final String COMPONENT_FAMILY = "javax.faces.Component";
+ public static final String COMPONENT_TYPE = "org.apache.myfaces.orchestra.flow.components.ModalFlow";
+
+ private String outcome;
+ private String onEntry;
+
+ // transient property
+ private boolean active = false;
+
+ public String getFamily()
+ {
+ return COMPONENT_FAMILY;
+ }
+
+ /**
+ * The optional flow outcome that causes this component to render the onEntry script.
+ * <p>
+ * When set, then this component will render the onEntry script (ie cause a new flow
+ * to be modal) only when a new flow is triggered by a matching outcome value. Calls
+ * to flows triggered by other outcomes will cause the current page to be replaced
+ * by the flow entry page (as normal) rather than running the flow in a modal window.
+ * <p>
+ * When not set (ie when null), any flowCall triggered by the containing page will
+ * activate this component (run as a modal flow).
+ * <p>
+ * Static value only (EL expressions not supported).
+ */
+ public String getOutcome()
+ {
+ return outcome;
+ }
+
+ public void setOutcome(String outcome)
+ {
+ this.outcome = outcome;
+ }
+
+ /**
+ * Specify some javascript that will be executed when this component is
+ * triggered by a flow call.
+ * <p>
+ * Static value only (EL expressions not supported).
+ */
+ public String getOnEntry()
+ {
+ return onEntry;
+ }
+
+ public void setOnEntry(String script)
+ {
+ this.onEntry = script;
+ }
+
+ /**
+ * Cause this component to render the onEntry script that shows the associated modal dialog.
+ * <p>
+ * This is called by the Orchestra Flow framework when the containing view has returned an
+ * outcome which triggers a flow and which matches the outcome property of this component.
+ */
+ public void setActive(boolean state)
+ {
+ this.active = state;
+ }
+
+ // ================ State Methods =================
+
+ public void restoreState(FacesContext context, Object state)
+ throws FacesException
+ {
+ Object[] states = (Object[]) state;
+ super.restoreState(context, states[0]);
+ outcome = (String) states[1];
+ onEntry = (String) states[2];
+
+ // While restoring view, add self to request scope, so that the
+ // FlowNavigationHandler can find it, activate it, and trigger
+ // re-render of the current view rather than actually doing
+ // navigation to the flow entry page.
+ //
+ // Note that a null outcome is valid.
+
+ Map reqMap = context.getExternalContext().getRequestMap();
+ Map flowMap = (Map) reqMap.get("modalFlows");
+ if (flowMap == null)
+ {
+ flowMap = new HashMap();
+ reqMap.put("modalFlows", flowMap);
+ }
+ if (flowMap.containsKey(outcome))
+ {
+ throw new FacesException("Duplicate ModalFlows with same outcome");
+ }
+ flowMap.put(outcome, this);
+ }
+
+ public Object saveState(FacesContext context)
+ {
+ return new Object[]
+ {
+ super.saveState(context),
+ outcome,
+ onEntry,
+ };
+ }
+
+ // ============ Renderer methods =================
+
+ /**
+ * When this component is active (postback for the containing view
+ * has just triggered a flowcall using an outcome matching this
+ * component), render the onEntry javascript.
+ * <p>
+ * When this component is not active, nothing is rendered.
+ */
+ public void encodeBegin(FacesContext context) throws IOException
+ {
+ super.encodeBegin(context);
+
+ if (active)
+ {
+ // Here, output script. We assume that this component is later
+ // within the page than whatever defines the function that this
+ // script calls.
+ //
+ // TODO: maybe here we should use StringSubstitutor to insert
+ // variables like ${viewURL} into the provided script?
+ ResponseWriter rw = context.getResponseWriter();
+ rw.startElement("script", this);
+ rw.write(onEntry);
+ rw.endElement("script");
+ }
+ }
+
+ // ============ Static methods =================
+
+ /**
+ * Determines whether the most recently restored view contains a ModalFlow
+ * component that maps to this outcome;
+ */
+ public static ModalFlow getForOutcome(FacesContext context, String outcome)
+ {
+ Map reqMap = context.getExternalContext().getRequestMap();
+ Map flowMap = (Map) reqMap.get("modalFlows");
+ if (flowMap == null)
+ {
+ return null;
+ }
+
+ ModalFlow mf = (ModalFlow) flowMap.get(outcome);
+ if (mf != null)
+ {
+ return mf;
+ }
+
+ // look for a global one
+ return (ModalFlow) flowMap.get(null);
+ }
+
+}
Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlow.java
------------------------------------------------------------------------------
svn:executable = *
Added: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java?rev=679791&view=auto
==============================================================================
--- myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java (added)
+++ myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java Fri Jul 25 06:09:54 2008
@@ -0,0 +1,61 @@
+/*
+ * 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.myfaces.orchestra.flow.components;
+
+import javax.faces.component.UIComponent;
+
+import org.apache.myfaces.shared_orchestra.taglib.UIComponentTagBase;
+
+/**
+ * Tag for ModalFlow component.
+ */
+public class ModalFlowTag extends UIComponentTagBase
+{
+ private String outcome;
+ private String onEntry;
+
+ public String getComponentType()
+ {
+ return ModalFlow.COMPONENT_TYPE;
+ }
+
+ protected void setProperties(UIComponent component)
+ {
+ super.setProperties(component);
+
+ setStringProperty(component, "outcome", outcome);
+ setStringProperty(component, "onEntry", onEntry);
+ }
+
+ public void setOutcome(String outcome)
+ {
+ this.outcome = outcome;
+ }
+
+ public void setOnEntry(String onEntry)
+ {
+ this.onEntry = onEntry;
+ }
+
+ public String getRendererType()
+ {
+ return null;
+ }
+}
Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: myfaces/orchestra/trunk/flow/src/main/java/org/apache/myfaces/orchestra/flow/components/ModalFlowTag.java
------------------------------------------------------------------------------
svn:executable = *