/* * � Copyright IBM Corp. 2010, 2013 * * Licensed 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 com.ibm.xsp.extlib.component.mobile; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; import com.ibm.commons.util.StringUtil; import com.ibm.xsp.complex.Attr; import com.ibm.xsp.component.FacesAttrsObject; import com.ibm.xsp.component.FacesComponent; import com.ibm.xsp.context.FacesContextEx; import com.ibm.xsp.extlib.component.util.DynamicUIUtil; import com.ibm.xsp.page.FacesComponentBuilder; import com.ibm.xsp.util.StateHolderUtil; import com.ibm.xsp.util.TypedUtil; /** * Mobile page. * <p> * In a typical mobile application, there is one main HTML page that is loaded and there is * no further navigation. But this HTML page contains fragments that are displayed or * hidden depending on the user actions. This makes the web applications look/behave similarly * to native applications.<br> * This class defines such a fragment. See dojox.mobile.View for deeper technical information. * </p> * @author Philippe Riand */ public class UIMobilePage extends UIComponentBase implements FacesComponent, FacesAttrsObject { public static final String PARAM_RESET = "resetContent"; // $NON-NLS-1$ public static final String DEFAULT_DOJO_TYPE = "extlib.dijit.Mobile"; // $NON-NLS-1$ public static final int ACTION_MOVETO_PAGE = 2; public static final String RENDERER_TYPE = "com.ibm.xsp.extlib.mobile.MobilePage"; //$NON-NLS-1$ public static final String COMPONENT_FAMILY = "com.ibm.xsp.extlib.Mobile"; //$NON-NLS-1$ public static final String COMPONENT_TYPE = "com.ibm.xsp.extlib.mobile.AppPage"; //$NON-NLS-1$ public static class Action { private String clientId; private int action; private String targetId; private String transitionType; private int direction; private Map<String,Object> hashParams; Action(FacesContext context, UIMobilePage dialog, int action) { this.clientId = dialog.getClientId(context); this.action = action; } Action(FacesContext context, UIMobilePage dialog, int action, String targetID, int direction, String transitionType, Map<String,Object> hashParams ) { this.clientId = dialog.getClientId(context); this.action = action; this.targetId = targetID; this.direction = direction; this.transitionType = transitionType; this.hashParams = hashParams; } public String getClientId() { return clientId; } public int getAction() { return action; } public String getTargetId() { return targetId; } public Map<String,Object> getHashParams() { return hashParams; } public String getTransitionType() { return transitionType; } public int getDirection() { return direction; } } private transient Action pendingAction; private Boolean selected; private Boolean keepScrollPos; // XPages Extension private Boolean resetContent; private Boolean autoCreate; private Boolean preload; private String pageName; private List<Attr> _attrs; private String onBeforeTransitionIn; private String onAfterTransitionIn; private String onBeforeTransitionOut; private String onAfterTransitionOut; public UIMobilePage() { setRendererType(RENDERER_TYPE); } @Override public String getFamily() { return COMPONENT_FAMILY; } public UIMobilePageContent getPopupContent() { List<UIComponent> children = TypedUtil.getChildren(this); if(!children.isEmpty()) { return (UIMobilePageContent)children.get(0); } return null; } public String getPageName() { if (null != this.pageName) { return this.pageName; } ValueBinding _vb = getValueBinding("pageName"); //$NON-NLS-1$ if (_vb != null) { String val = (java.lang.String) _vb.getValue(FacesContext.getCurrentInstance()); if(val!=null) { return val; } } return null; } public void setPageName(String pageName) { this.pageName = pageName; } @Override public String getClientId(FacesContext context){ String pageName = getPageName(); if(pageName != null){ return pageName; }else{ return super.getClientId(context); } } public boolean isPreload() { if (null != this.preload) { return this.preload; } ValueBinding _vb = getValueBinding("preload"); //$NON-NLS-1$ if (_vb != null) { Boolean val = (java.lang.Boolean) _vb.getValue(FacesContext.getCurrentInstance()); if(val!=null) { return val; } } return false; } public void setPreload(boolean preload) { this.preload = preload; } public void setSelected (boolean selected) { this.selected = selected; } public boolean isKeepScrollPos() { if (null != this.keepScrollPos) { return this.keepScrollPos; } ValueBinding _vb = getValueBinding("keepScrollPos"); //$NON-NLS-1$ if (_vb != null) { Boolean val = (java.lang.Boolean) _vb.getValue(FacesContext.getCurrentInstance()); if(val!=null) { return val; } } return true; } public void setKeepScrollPos(boolean keepScrollPos) { this.keepScrollPos = keepScrollPos; } public boolean isResetContent() { if (null != this.resetContent) { return this.resetContent; } ValueBinding _vb = getValueBinding("resetContent"); //$NON-NLS-1$ if (_vb != null) { Boolean val = (java.lang.Boolean) _vb.getValue(FacesContext.getCurrentInstance()); if(val!=null) { return val; } } return false; } public void setResetContent(boolean resetContent) { this.resetContent = resetContent; } public boolean isAutoCreate() { if (null != this.autoCreate) { return this.autoCreate; } ValueBinding _vb = getValueBinding("autoCreate"); //$NON-NLS-1$ if (_vb != null) { Boolean val = (java.lang.Boolean) _vb.getValue(FacesContext.getCurrentInstance()); if(val!=null) { return val; } } return false; } public void setAutoCreate(boolean autoCreate) { this.autoCreate = autoCreate; } /** * The extra attributes to be output on the base element at the root of this * control or object tag. This should only be used when none of the * properties in the All Properties pane correspond to the desired * attribute. This may return <code>null</code>. The {@link #addAttr(Attr)} * method should be used to add an Attr. */ public List<Attr> getAttrs() { return _attrs; } /** * Add an Attr, to appear as an attribute in the HTML output of this control * or object tag. * * @param action */ public void addAttr(Attr attr) { if(_attrs==null) { _attrs = new ArrayList<Attr>(); } _attrs.add(attr); } public String getOnBeforeTransitionIn() { if (null != this.onBeforeTransitionIn) { return this.onBeforeTransitionIn; } ValueBinding vb = getValueBinding("onBeforeTransitionIn"); //$NON-NLS-1$ if (vb != null) { return (String) vb.getValue(getFacesContext()); } else { return null; } } public void setOnBeforeTransitionIn(String onBeforeTransitionIn) { this.onBeforeTransitionIn = onBeforeTransitionIn; } public String getOnAfterTransitionIn() { if (null != this.onAfterTransitionIn) { return this.onAfterTransitionIn; } ValueBinding vb = getValueBinding("onAfterTransitionIn"); //$NON-NLS-1$ if (vb != null) { return (String) vb.getValue(getFacesContext()); } else { return null; } } public void setOnAfterTransitionIn(String onAfterTransitionIn) { this.onAfterTransitionIn = onAfterTransitionIn; } public String getOnBeforeTransitionOut() { if (null != this.onBeforeTransitionOut) { return this.onBeforeTransitionOut; } ValueBinding vb = getValueBinding("onBeforeTransitionOut"); //$NON-NLS-1$ if (vb != null) { return (String) vb.getValue(getFacesContext()); } else { return null; } } public void setOnBeforeTransitionOut(String onBeforeTransitionOut) { this.onBeforeTransitionOut = onBeforeTransitionOut; } public String getOnAfterTransitionOut() { if (null != this.onAfterTransitionOut) { return this.onAfterTransitionOut; } ValueBinding vb = getValueBinding("onAfterTransitionOut"); //$NON-NLS-1$ if (vb != null) { return (String) vb.getValue(getFacesContext()); } else { return null; } } public void setOnAfterTransitionOut(String onAfterTransitionOut) { this.onAfterTransitionOut = onAfterTransitionOut; } // State management @Override public void restoreState(FacesContext _context, Object _state) { Object _values[] = (Object[]) _state; super.restoreState(_context, _values[0]); this.selected = (Boolean)_values[1]; this.keepScrollPos = (Boolean)_values[2]; this.resetContent = (Boolean)_values[3]; this.autoCreate = (Boolean)_values[4]; this.preload = (Boolean)_values[5]; this.pageName = (String)_values[6]; this._attrs = StateHolderUtil.restoreList(_context, this, _values[7]); this.onBeforeTransitionIn = (String) _values[8]; this.onAfterTransitionIn = (String) _values[9]; this.onBeforeTransitionOut = (String) _values[10]; this.onAfterTransitionOut = (String) _values[11]; } @Override public Object saveState(FacesContext _context) { Object _values[] = new Object[12]; _values[0] = super.saveState(_context); _values[1] = selected; _values[2] = keepScrollPos; _values[3] = resetContent; _values[4] = autoCreate; _values[5] = preload; _values[6] = pageName; _values[7] = StateHolderUtil.saveList(_context, _attrs); _values[8] = onBeforeTransitionIn; _values[9] = onAfterTransitionIn; _values[10] = onBeforeTransitionOut; _values[11] = onAfterTransitionOut; return _values; } // ============================================================= // Methods for scripting // ============================================================= /** * @deprecated does nothing */ public void show() { show(null); } /** * @deprecated does nothing */ public void show(Map<String,Object> refreshParams) { } public void createMoveToAction ( String targetID, int direction, String transitionType, Map<String,Object> hashParams ) { FacesContextEx context = FacesContextEx.getCurrentInstance(); UIMobilePageContent popup = getPopupContent(); if(popup.isContentCreated()) { // Remove the content pendingAction = new Action(context,this,ACTION_MOVETO_PAGE,targetID,direction,transitionType,hashParams); } } public Action getPendingAction(FacesContext context) { if(pendingAction!=null) { String cid = getClientId(context); if(StringUtil.equals(cid, pendingAction.clientId)) { Action temp = pendingAction; pendingAction = null; return temp; } } return null; } // ============================================================= // Control construction // ============================================================= public void initBeforeContents(FacesContext context) throws FacesException { // do nothing, method needed because implementing FacesComponent } public void buildContents(FacesContext context, FacesComponentBuilder builder) throws FacesException { boolean isDynamicallyConstructing = (getParent() instanceof UIMobilePageTempContainer); if( isDynamicallyConstructing ) { // This is called when the control content is created dynamically // The appPageContent is trying to load its content in response to // a user event (so after createView). While attempting to load the // content, the process will create a temporary UIMobilePage // under the UIMobilePageContent control. This UIMobilePage is // that temporary UIMobilePage. UIMobilePageTempContainer tempContainer = (UIMobilePageTempContainer) getParent(); UIMobilePageContent appPageContent = (UIMobilePageContent) tempContainer.getParent(); appPageContent.buildDynamicContents(context, builder); } else { // This is called when the xsp page is created (the main component tree) // Used for creating the inner content dynamically String sourcePageName = DynamicUIUtil.getSourcePageName(builder); UIMobilePageContent content = new UIMobilePageContent(sourcePageName); // This id of the popup panel is the id of the page with a suffix content.setId(getId()+"_content"); // $NON-NLS-1$ TypedUtil.getChildren(this).add(content); content.buildInitialContents(context, builder); } } public void initAfterContents(FacesContext context) throws FacesException { // do nothing, method needed because implementing FacesComponent } }