247 lines
9.3 KiB
Java
247 lines
9.3 KiB
Java
/*
|
|
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Declarative Engineering LLC
|
|
* verson 1 which accompanies this distribution, and is available at
|
|
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
|
*/
|
|
package com.foundation.controller;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
import com.common.debug.*;
|
|
import com.common.thread.IRunnable;
|
|
import com.foundation.attribute.ReflectionContext;
|
|
import com.foundation.view.*;
|
|
|
|
/**
|
|
* Provides extra support for remote views where the display occurs on a remote process from the model and controller code.
|
|
*/
|
|
public abstract class RemoteViewController extends AbstractViewController {
|
|
/** The remote view context is a reference to the object supporting just this view (versus the view context which supports a system of remote views across a single connection). This must be null if this view is open inside another view. */
|
|
private IRemoteViewContext remoteViewContext = null;
|
|
/**
|
|
* RemoteViewController constructor.
|
|
* @param viewContext The view's context under which it will operate.
|
|
*/
|
|
public RemoteViewController(IViewContext viewContext) {
|
|
super(viewContext);
|
|
}//RemoteViewController()//
|
|
/**
|
|
* RemoteViewController constructor.
|
|
* @param viewContext The view's context under which it will operate.
|
|
* @param reflectionContext The reflection context to be used by the view.
|
|
*/
|
|
public RemoteViewController(IViewContext context, ReflectionContext reflectionContext) {
|
|
super(context, reflectionContext);
|
|
}//RemoteViewController()//
|
|
/**
|
|
* RemoteViewController constructor.
|
|
* @param viewContext The view's context under which it will operate.
|
|
* @param validateOnOpen Whether the view should perform validation immediately after opening. This is true by default.
|
|
*/
|
|
public RemoteViewController(IViewContext viewContext, boolean validateOnOpen) {
|
|
super(viewContext, validateOnOpen);
|
|
}//RemoteViewController()//
|
|
/**
|
|
* RemoteViewController constructor.
|
|
* @param viewContext The view's context under which it will operate.
|
|
* @param reflectionContext The reflection context to be used by the view.
|
|
* @param validateOnOpen Whether the view should perform validation immediately after opening. This is true by default.
|
|
*/
|
|
public RemoteViewController(IViewContext context, ReflectionContext reflectionContext, boolean validateOnOpen) {
|
|
super(context, reflectionContext, validateOnOpen);
|
|
}//RemoteViewController()//
|
|
/**
|
|
* Gets the remote view context under which this view controller is operating.
|
|
* @return The view context specific to this remote view controller.
|
|
*/
|
|
public IRemoteViewContext getRemoteViewContext() {
|
|
//The remote view context will be null if this view is open inside another view.//
|
|
return remoteViewContext != null ? remoteViewContext : ((RemoteViewController) getParentComponent().getController()).getRemoteViewContext();
|
|
}//getRemoteViewContext()//
|
|
/**
|
|
* Creates the controller's primary view component.
|
|
* @return This view controller's new view object.
|
|
*/
|
|
protected IView createView() {
|
|
Class viewClass = getViewClass();
|
|
IView result = null;
|
|
|
|
if(viewClass == null) {
|
|
Debug.log("Error: getViewClass() must return a valid view class in the remote view controller " + getClass().getName());
|
|
}//if//
|
|
|
|
try {
|
|
if(getParentComponent() == null) {
|
|
Constructor constructor = viewClass.getConstructor(new Class[] {RemoteViewController.class});
|
|
|
|
result = (IView) constructor.newInstance(new Object[] {this});
|
|
}//if//
|
|
else {
|
|
Constructor constructor = viewClass.getConstructor(new Class[] {RemoteViewController.class, IView.class});
|
|
|
|
result = (IView) constructor.newInstance(new Object[] {this, getParentComponent()});
|
|
}//else//
|
|
}//try//
|
|
catch(NoSuchMethodException e) {
|
|
Debug.log(e);
|
|
}//catch//
|
|
catch(InvocationTargetException e) {
|
|
Debug.log(e);
|
|
}//catch//
|
|
catch(InstantiationException e) {
|
|
Debug.log(e);
|
|
}//catch//
|
|
catch(IllegalAccessException e) {
|
|
Debug.log(e);
|
|
}//catch//
|
|
|
|
return result;
|
|
}//createView()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.controller.AbstractViewController#internalClose(com.foundation.view.IView, java.lang.Runnable, java.lang.Runnable)
|
|
*/
|
|
protected void internalClose(IView view, Runnable onCloseHandler, Runnable onDisposeHandler) {
|
|
IRemoteViewContext viewContext = null;
|
|
|
|
synchronized(this) {
|
|
viewContext = getParentComponent() == null ? this.remoteViewContext : null;
|
|
this.remoteViewContext = null;
|
|
}//synchronized//
|
|
|
|
//Hide the view and call the on close handler.//
|
|
view.setIsVisible(false); //TODO: Can this be enclosed in the message hold area below?//
|
|
|
|
if(onCloseHandler != null) {
|
|
onCloseHandler.run();
|
|
}//if//
|
|
|
|
//Release the view on the client.//
|
|
view.addMessageHold();
|
|
view.viewReleaseAll();
|
|
postClose();
|
|
view.removeMessageHold();
|
|
|
|
if(viewContext != null && viewContext.isValid()) {
|
|
//Notify the session view controller to release its self.//
|
|
viewContext.close();
|
|
}//if//
|
|
|
|
if(onDisposeHandler != null) {
|
|
onDisposeHandler.run();
|
|
}//if//
|
|
}//internalClose()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.controller.AbstractViewController#internalInitialize()
|
|
*/
|
|
protected IView internalInitialize() {
|
|
IView result = null;
|
|
|
|
if(getContext() != null) {
|
|
remoteViewContext.incrementMessageHoldCount();
|
|
result = createView();
|
|
}//if//
|
|
else {
|
|
Debug.log("Error: Cannot open the view without a proper view context.");
|
|
}//else//
|
|
|
|
return result;
|
|
}//internalInitialize()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.controller.AbstractViewController#internalInitializeContext(com.foundation.view.IViewContext)
|
|
*/
|
|
protected void internalInitializeContext(IViewContext context) {
|
|
if((context != null) && (context instanceof IRemoteSessionContext)) {
|
|
//This creates a new remote session context which is a proxy to an object on the client that represents the view.//
|
|
//This should not be done for inner views (views that exist inside other views). Instead those views should use their parent's context.//
|
|
remoteViewContext = ((IRemoteSessionContext) context).createViewContext(this);
|
|
}//if//
|
|
else {
|
|
Debug.log("Error: Cannot open the view without a proper view context.");
|
|
}//else//
|
|
}//internalInitializeContext()//
|
|
/* (non-Javadoc)
|
|
* @see com.foundation.controller.AbstractViewController#internalOpen(IView)
|
|
*/
|
|
protected void internalOpen(final IView view) {
|
|
view.execute(new com.common.thread.IRunnable() {
|
|
public Object run() {
|
|
view.suspendLayouts();
|
|
view.viewInitializeAll();
|
|
view.resumeLayouts();
|
|
view.layout();
|
|
view.pack();
|
|
postOpenInitialization(view);
|
|
|
|
if(validateOnOpen()) {
|
|
validate();
|
|
}//if//
|
|
|
|
remoteViewContext.decrementMessageHoldCount();
|
|
|
|
return null;
|
|
}//run()//
|
|
});
|
|
}//internalOpen()//
|
|
/**
|
|
* Opens a partial view given the view's parent view component reference and an optional view context.
|
|
* <p>This is intended only to be called by the containing view when it requires the sub-component to be created.</p>
|
|
* <p><b>Warning: This method is not thread safe. It is assumed that the view will be owned by one parent component and will be opened only by that component.</b></p>
|
|
* @param parent The non-null parent view component passed by the view.
|
|
* @param context The context for the view. The actual value is dependant upon the view framework being used. In a remote view this value may be the session context for example.
|
|
* @return A view associated with this view controller that is a part of another view.
|
|
*/
|
|
public IView openPartial(IView parent, Object context) {
|
|
IView view = null;
|
|
|
|
if(parent == null) {
|
|
throw new RuntimeException("Error: Cannot open a partial view without a parent view part.");
|
|
}//if//
|
|
else if(context != getContext()) {
|
|
throw new RuntimeException("Error: Invalid view context. This view was initialized with a different context than it is being used under.");
|
|
}//else if//
|
|
|
|
if(getView() == null) {
|
|
setOptions(0);
|
|
setParentComponent(parent);
|
|
setView(view = createView());
|
|
view.addMessageHold();
|
|
view.suspendLayouts();
|
|
getDecorationManager().initialize(getView());
|
|
isOpen(true);
|
|
view.setController(this);
|
|
view.viewInitializeAll();
|
|
view.resumeLayouts();
|
|
view.layout();
|
|
//view.pack();
|
|
//postOpenInitialization(view);
|
|
view.removeMessageHold();
|
|
validate();
|
|
}//if//
|
|
|
|
return view;
|
|
}//openPartialView()//
|
|
/**
|
|
* Executes the runnable on the view's event thread.
|
|
* <p>It is necessary to run most view related operations on the view thread since all views and all associated model and controller objects are not thread safe.</p>
|
|
*/
|
|
public final Object execute(IRunnable runnable) {
|
|
return getRemoteViewContext().execute(runnable);
|
|
}//execute()//
|
|
/**
|
|
* Executes the runnable on the view's event thread and returns immediatly.
|
|
* <p>It is necessary to run most view related operations on the view thread since all views and all associated model and controller objects are not thread safe.</p>
|
|
*/
|
|
public final void executeAsync(IRunnable runnable) {
|
|
getRemoteViewContext().executeAsync(runnable);
|
|
}//executeAsync()//
|
|
/**
|
|
* Gets the display metadata which describes the client view system such as information about the display locations and sizes.
|
|
* @return The metadata describing the client view system.
|
|
*/
|
|
public ViewSystemMetadata getViewSystemMetadata() {
|
|
return getRemoteViewContext().getSessionContext().getViewSystemMetadata();
|
|
}//getViewSystemMetadata()//
|
|
}//RemoteViewController// |