/*
* 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;
}
}