/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jspresso is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.application.frontend.controller.remote.mobile; import java.util.List; import java.util.Map; import org.jspresso.framework.action.ActionContextConstants; import org.jspresso.framework.application.frontend.action.workspace.WorkspaceSelectionAction; import org.jspresso.framework.application.frontend.command.remote.mobile.RemoteAnimationCommand; import org.jspresso.framework.application.frontend.command.remote.mobile.RemoteBackCommand; import org.jspresso.framework.application.frontend.controller.remote.AbstractRemoteController; import org.jspresso.framework.application.model.Module; import org.jspresso.framework.application.model.Workspace; import org.jspresso.framework.binding.ICompositeValueConnector; import org.jspresso.framework.binding.IValueConnector; import org.jspresso.framework.gui.remote.RAction; import org.jspresso.framework.gui.remote.RCardContainer; import org.jspresso.framework.gui.remote.RComponent; import org.jspresso.framework.gui.remote.RIcon; import org.jspresso.framework.gui.remote.mobile.RMobileCardPage; import org.jspresso.framework.gui.remote.mobile.RMobileNavPage; import org.jspresso.framework.gui.remote.mobile.RMobilePage; import org.jspresso.framework.util.gui.Dimension; import org.jspresso.framework.util.gui.EClientType; import org.jspresso.framework.view.IView; import org.jspresso.framework.view.descriptor.IViewDescriptor; /** * This is is the mobile implementation of a "remotable" frontend * controller. * * @author Vincent Vandenschrick * @version $LastChangedRevision : 8508 $ */ public class MobileRemoteController extends AbstractRemoteController { private boolean singleModuleWorkspaceShortcut; public MobileRemoteController() { singleModuleWorkspaceShortcut = true; } /** * Not supported in mobile environment. * <p/> * {@inheritDoc} * * @param plainContent * the plain content * @param htmlContent * the html content */ @Override public void setClipboardContent(String plainContent, String htmlContent) { throw new UnsupportedOperationException("Not supported in mobile environment."); } /** * Not supported in mobile environment. * <p/> * {@inheritDoc} * * @param swfUrl * the swf url * @param flashContext * the flash context * @param actions * the actions * @param title * the title * @param sourceComponent * the source component * @param context * the context * @param dimension * the dimension * @param reuseCurrent * the reuse current */ @Override public void displayFlashObject(String swfUrl, Map<String, String> flashContext, List<RAction> actions, String title, RComponent sourceComponent, Map<String, Object> context, Dimension dimension, boolean reuseCurrent) { throw new UnsupportedOperationException("Not supported in mobile environment."); } /** * Navigate back. * * @param context * the context */ @SuppressWarnings("unchecked") public void navigateBack(Map<String, Object> context) { registerCommand(new RemoteBackCommand()); if (context != null) { // Update the context as if the view had changed. IView<RComponent> view = (IView<RComponent>) context.get(ActionContextConstants.VIEW); if (view != null) { view = view.getParent(); if (view != null) { context.put(ActionContextConstants.VIEW, view); context.put(ActionContextConstants.VIEW_CONNECTOR, view.getConnector()); } } } } /** * Animate page. * * @param page * the page * @param animation * the animation * @param direction * the direction * @param reverse * the reverse * @param duration * the duration * @param hideView * the hide view * @param callbackAction * the callback action */ public void animatePage(RMobilePage page, String animation, String direction, boolean reverse, int duration, boolean hideView, RAction callbackAction) { RemoteAnimationCommand command = new RemoteAnimationCommand(); if (page != null) { command.setTargetPeerGuid(page.getGuid()); } command.setAnimation(animation); command.setDirection(direction); command.setReverse(reverse); command.setDuration(duration); command.setHideView(hideView); command.setCallbackAction(callbackAction); registerCommand(command); } /** * {@inheritDoc} * * @param workspaceName * the workspace name * @return the r component */ @Override protected RComponent createWorkspaceView(String workspaceName) { Workspace workspace = getWorkspace(workspaceName); List<Module> modules = workspace.getModules(); IView<RComponent> moduleAreaView = createModuleAreaView(workspaceName); RMobileCardPage moduleAreaPage = new RMobileCardPage(workspaceName + "_moduleArea"); moduleAreaPage.setPages((RCardContainer) moduleAreaView.getPeer()); if (isShortcutToSingleModule(modules)) { return moduleAreaPage; } else { RMobileNavPage viewComponent = new RMobileNavPage(workspaceName + "_navigation"); viewComponent.setLabel(workspace.getI18nName()); viewComponent.setToolTip(workspace.getI18nDescription()); viewComponent.setHeaderText(workspace.getI18nPageHeaderDescription()); IViewDescriptor workspaceNavigatorViewDescriptor = workspace.getViewDescriptor(); IValueConnector workspaceConnector = getBackendController().getWorkspaceConnector(workspaceName); IView<RComponent> workspaceNavigator = createWorkspaceNavigator(workspaceName, workspaceNavigatorViewDescriptor); viewComponent.setSelectionView(workspaceNavigator.getPeer()); viewComponent.setNextPage(moduleAreaPage); getMvcBinder().bind(workspaceNavigator.getConnector(), workspaceConnector); return viewComponent; } } private boolean isShortcutToSingleModule(List<Module> modules) { return isSingleModuleWorkspaceShortcut() && modules != null && modules.size() == 1 && (modules.get(0).getSubModules() == null || modules.get(0).getSubModules().isEmpty()); } /** * Handle workspace navigator selection. Resets selection if selected module is null in order to re-arm client list. * * @param workspaceName * the workspace name * @param selectedConnector * the selected connector */ @Override protected void handleWorkspaceNavigatorSelection(String workspaceName, ICompositeValueConnector selectedConnector) { if (selectedConnector != null && selectedConnector.getConnectorValue() instanceof Module) { Module selectedModule = selectedConnector.getConnectorValue(); displayModule(workspaceName, selectedModule); } else { displayModule(workspaceName, null); } } /** * {@inheritDoc} */ @Override protected void displayWorkspace(String workspaceName, boolean bypassModuleBoundaryActions) { boolean navigateToModule = workspaceName != null && !workspaceName.equals(getSelectedWorkspaceName()); super.displayWorkspace(workspaceName, bypassModuleBoundaryActions); if (navigateToModule) { Workspace workspace = getWorkspace(workspaceName); List<Module> modules = workspace.getModules(); if (isShortcutToSingleModule(modules)) { Module singleModule = modules.get(0); // This is a hack to detect that we are called for the second time. So we must not re-display the module, // otherwise the entry action is executed twice. if (!bypassModuleBoundaryActions) { displayModule(singleModule); } } } } /** * Sets single module workspace shortcut. * * @param singleModuleWorkspaceShortcut * the single module workspace shortcut */ public void setSingleModuleWorkspaceShortcut(boolean singleModuleWorkspaceShortcut) { this.singleModuleWorkspaceShortcut = singleModuleWorkspaceShortcut; } /** * Is single module workspace shortcut boolean. * * @return the boolean */ protected boolean isSingleModuleWorkspaceShortcut() { return singleModuleWorkspaceShortcut; } @Override protected WorkspaceSelectionAction<RComponent, RIcon, RAction> createWorkspaceSelectionAction(String workspaceName, IViewDescriptor workspaceViewDescriptor) { WorkspaceSelectionAction<RComponent, RIcon, RAction> workspaceSelectionAction = super .createWorkspaceSelectionAction(workspaceName, workspaceViewDescriptor); workspaceSelectionAction.setForceReselection(getClientType() == EClientType.MOBILE_HTML5_PHONE); return workspaceSelectionAction; } }