/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.e4.launcher.binder;
import javax.inject.Inject;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.riena.e4.launcher.rendering.RienaWBWRenderer;
import org.eclipse.riena.internal.ui.ridgets.swt.uiprocess.UIProcessRidget;
import org.eclipse.riena.navigation.IModuleGroupNode;
import org.eclipse.riena.navigation.IModuleNode;
import org.eclipse.riena.navigation.ISubApplicationNode;
import org.eclipse.riena.navigation.NavigationNodeId;
import org.eclipse.riena.navigation.listener.SubApplicationNodeListener;
import org.eclipse.riena.navigation.ui.controllers.SubApplicationController;
import org.eclipse.riena.navigation.ui.swt.binding.DelegatingRidgetMapper;
import org.eclipse.riena.navigation.ui.swt.binding.InjectSwtViewBindingDelegate;
import org.eclipse.riena.navigation.ui.swt.presentation.SwtViewProvider;
import org.eclipse.riena.navigation.ui.swt.views.SubApplicationView;
import org.eclipse.riena.ui.ridgets.controller.IController;
import org.eclipse.riena.ui.ridgets.swt.uibinding.AbstractViewBindingDelegate;
import org.eclipse.riena.ui.ridgets.swt.uibinding.SwtControlRidgetMapper;
import org.eclipse.riena.ui.swt.uiprocess.UIProcessControl;
/**
* Creates and binds an instance of {@link SubApplicationController}. This is a replacement for riena {@link SubApplicationView}. Moreover {@link #bind()}
* honors the possibility of a non existing {@link Shell}. For that case the {@link IEventBroker} is used. As soon as the {@link Shell} is created by the
* {@link RienaWBWRenderer} the listener gets notified.
*/
@SuppressWarnings("restriction")
public class SubApplicationBinder {
@Inject
private IEclipseContext context;
@Inject
private IEventBroker eventBroker;
private final ISubApplicationNode subApplicationNode;
private final AbstractViewBindingDelegate binding;
private SubApplicationListener subApplicationListener;
private SubApplicationController subApplicationController;
public SubApplicationBinder(final ISubApplicationNode subApplicationNode) {
this.subApplicationNode = subApplicationNode;
binding = createBinding();
}
protected AbstractViewBindingDelegate createBinding() {
final DelegatingRidgetMapper ridgetMapper = new DelegatingRidgetMapper(SwtControlRidgetMapper.getInstance());
ridgetMapper.addMapping(UIProcessControl.class, UIProcessRidget.class);
return new InjectSwtViewBindingDelegate(ridgetMapper);
}
private void createUIProcessControl(final Shell shell) {
final UIProcessControl uiControl = new UIProcessControl(shell);
uiControl.setPropertyName("uiProcessRidget"); //$NON-NLS-1$
binding.addUIControl(uiControl);
}
/**
* Binds the navigation node to the view. Creates the widgets and the controller if necessary.<br>
* Also the menus and the tool bar items are binded.
*
* @see org.eclipse.riena.navigation.ui.swt.views.INavigationNodeView#bind(org.eclipse.riena.navigation.INavigationNode)
*/
public void bind() {
subApplicationController = new SubApplicationController(subApplicationNode);
subApplicationController.installNavigationListeners();
final Object shell = context.get(IServiceConstants.ACTIVE_SHELL);
if (null == shell) {
eventBroker.subscribe(RienaWBWRenderer.SHELL_CREATED, new LazyBinder());
return;
}
internalBind(shell);
}
/**
* Lazy binding for the case that the {@link Shell} is not available yet.
*/
private final class LazyBinder implements EventHandler {
public void handleEvent(final Event event) {
internalBind(event.getProperty(IEventBroker.DATA));
}
}
private void internalBind(final Object shell) {
createUIProcessControl((Shell) shell);
bindController();
}
private void bindController() {
if (subApplicationController.getRidgets().isEmpty()) {
binding.injectRidgets(subApplicationController);
binding.bind(subApplicationController);
observeSubApplicationNode();
subApplicationController.afterBind();
}
}
private void observeSubApplicationNode() {
subApplicationListener = new SubApplicationListener();
getNavigationNode().addListener(subApplicationListener);
}
private class SubApplicationListener extends SubApplicationNodeListener {
@Override
public void block(final ISubApplicationNode source, final boolean block) {
super.block(source, block);
for (final IModuleGroupNode group : source.getChildren()) {
for (final IModuleNode module : group.getChildren()) {
module.setBlocked(block);
}
}
}
@Override
public void disposed(final ISubApplicationNode source) {
unbind();
}
@Override
public void nodeIdChange(final ISubApplicationNode source, final NavigationNodeId oldId, final NavigationNodeId newId) {
SwtViewProvider.getInstance().replaceNavigationNodeId(source, oldId, newId);
}
}
public void unbind() {
if (getNavigationNode() != null) {
getNavigationNode().removeListener(subApplicationListener);
if (getNavigationNode().getNavigationNodeController() instanceof IController) {
final IController controller = (IController) getNavigationNode().getNavigationNodeController();
binding.unbind(controller);
}
}
}
private ISubApplicationNode getNavigationNode() {
return subApplicationNode;
}
}