at.spardat.xma.appshell.Task Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* 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:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
/*
* @(#) $Id: Task.java 9060 2012-03-06 10:06:47Z hoenninger $
*
*
*
*
*/
package at.spardat.xma.appshell;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.boot.component.IComponent;
import at.spardat.xma.boot.component.IXMAControl;
import at.spardat.xma.component.ComponentClient;
import at.spardat.xma.page.IDialogPage;
import at.spardat.xma.page.IEmbeddable;
/**
* Tasks are java objects which implement a workflow in its method {@link #run()}.
*
* @author s2877
* @since 1.4.0
*/
public abstract class Task implements ITask {
/**
* The application shell containing this task.
*/
protected AppShell app;
private AppShellDelegate appDelegate;
/**
* The menu item containing this task.
*/
protected IMenuItem menu;
private ITask parentTask;
private ITask subTask;
private IEmbeddable epage;
private ComponentClient component;
private boolean runfinished;
private boolean cleanSubmenu = true; // defaults to old behaviour
private boolean autoDispose = true; // defaults to old behaviour
private boolean autoClose = false;
/**
* creates at Task
*/
public Task(ComponentClient comp) {
this.component=comp;
}
/**
* creates a Task
* @param app the AppShell containing the Task
*/
public Task(IAppShell app) {
setAppShell(app);
this.component=this.app.getComponent();
}
/**
* creates a Task
* @param app the AppShell containing the Task
* @param menu the MenuItem where this Task adds its submenu.
*/
public Task(IAppShell app,IMenuItem menu) {
this(app);
this.menu=menu;
}
/**
* Calls a component or page and waits until it is closed.
* The component or page is embeded in the client area of the application shell.
* @param page to embedd
*/
public void callBlocking(IXMAControl page) {
appDelegate.lockMenu();
try {
epage =(IEmbeddable) page;
appDelegate.showContextStack();
appDelegate.setClientArea(epage);
IDialogPage dialog = (IDialogPage) epage.getDialog();
dialog.setEventsEnabled(true);
clientEventLoop(page);
dialog.setEventsEnabled(false);
} finally {
if(appDelegate.hasWidgets()) { // if not disposed in the meantime
appDelegate.unlockMenu();
}
}
}
/**
* Calls a component or page and returns imediately.
* The component or page is embeded in the client area of the application shell.
* @param page to embedd
*/
public void callNonBlocking(IXMAControl page) {
callNonBlocking(page,null);
}
/**
* Calls a component or page and returns imediately.
* The component or page is embeded in the client area of the application shell.
* @param page to embedd
* @param clientCompositeW the composite to embedd into or null to use the default one
*/
public void callNonBlocking(IXMAControl page,Composite clientCompositeW) {
epage =(IEmbeddable) page;
appDelegate.setClientArea(page,clientCompositeW);
appDelegate.showContextStack();
}
/**
* Removes the component or page on top of the call stack.
* @param show if true refresh the screen
* if false the screen is not refreshed
*/
public void pageClosed(boolean show) {
if(epage!=null) {
IComponent toDispose=null;
if(autoDispose && epage instanceof IComponent) { // components must be disposed.
toDispose = (IComponent) epage;
}
epage=null; // must be set to null prior to calling showTopPage().
appDelegate.showContextStack();
if(show) {
showTopPage();
} else {
appDelegate.clearClientArea();
// app.setClientDirty();
}
if(toDispose!=null) { // dipose it after it is no longer embedded.
toDispose.dispose();
}
}
}
/**
* Refresh the page on top of the call stack to the screen.
*/
public void showTopPage() {
if(epage!=null) {
appDelegate.setClientArea(epage);
} else if(parentTask!=null) {
parentTask.showTopPage();
} else {
appDelegate.clearClientArea();
}
}
/**
* Starts the Task by calling it as subtask of the given parent task.
* @param parentTask
*/
public void start(ITask parentTask) {
parentTask.call(this);
}
/**
* Starts the Task by calling it as subtask of the task on top of the callstack of the
* given appShell.
* @param appShell
*/
public void start(IAppShell appShell) {
appShell.getTopTask().call(this);
}
/**
* Calls a Task as subtask of this Task.
* This attaches it on top of the call stack and calls it {@link #run()} method.
* @param subTask to call.
*/
public void call(ITask subTask) {
if(this.subTask!=null) {
throw new IllegalStateException("previous subtask still running");
}
if (this == subTask) {
throw new IllegalStateException("Can not add a task as its own sub task");
}
this.subTask=subTask;
subTask.setParentTask(this);
subTask.setAppShell(appDelegate);
subTask.run();
subTask.setRunfinished();
appDelegate.showContextStack();
if (subTask.isAutoClose()) {
subTask.closeRequested(true);
}
}
/**
* Closes the Task.
* @return true if the Task is closed successfully
* false if the Task refuses to close
*/
public boolean closeRequested() {
return closeRequested(false);
}
/**
* Closes the Task.
* @param show if true refresh the screen
* if false the screen is not refreshed
* @return true if the Task is closed successfully
* false if the Task refuses to close
*/
public boolean closeRequested(boolean show) {
if(subTask!=null) {
if(!subTask.closeRequested(show)) return false;
}
if(menu!=null&&cleanSubmenu) {
menu.clearItems();
}
if(parentTask!=null) {
parentTask.setSubTask(null);
}
pageClosed(show);
runfinished=false;
return true;
}
/**
* Get the parent Task of this Task. The parent Task is
* the Task that called this.
* @return the parent task
*/
public ITask getParentTask() {
return parentTask;
}
/**
* Get the direct subtask of this Task. The subtask is the
* currently active Task called by this.
* @return the direct successor on the call stack
*/
public ITask getSubTask() {
return subTask;
}
/**
* Get the page or component embedded or called by this Task
* @return the active component of this Task or null.
*/
public IEmbeddable getPage() {
return epage;
}
/**
* Execute an eventLoop for modal clients. This call blocks until
* the client is detached from the appshell by calling removeChild().
* Dispatches all events in the meantime.
*/
private void clientEventLoop(IXMAControl client) {
Display display = app.getShell().getDisplay();
while (client.getComposite()!=null) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Determine if the given MenuItem is contained directly in the submenu
* of the MenuItem of this Task.
* @param item to test
* @return true if this Task contains the given item.
*/
public boolean contains(IMenuItem item) {
if(menu==null) return false;
// return menu.equals(item) || menu.containsItem(item);
return menu.containsItem(item);
}
/**
* Get the context string of this task.
* @return the string to show as context in the enclosing AppShell or dialog.
*/
public String getContextString() {
return null;
}
/**
* Get the menu item of this Task. The menu item of this Task calls this
* Task when selected.
* @return the menu item of this Task.
*/
public IMenuItem getMenu() {
return menu;
}
/**
* Set the menu item of this Task. The menu item of this Task calls this
* Task when selected.
* @param item where this Task can add its submenu.
*/
public void setMenu(IMenuItem item) {
menu = item;
}
/**
* Set the parent Task of this Task. The parent Task is
* the Task that will call this.
* @param parent task to set.
*/
public void setParentTask(ITask parent) {
this.parentTask = parent;
}
/**
* Set the subtask of this Task. The subtask is the
* Task that will be called by this.
* @param subtask to set.
*/
public void setSubTask(ITask subtask) {
this.subTask = subtask;
}
/**
* Set the AppShell of this Task.
* @param appShell
*/
public void setAppShell(IAppShell appShell) {
if ( appShell instanceof AppShellDelegate ) {
this.appDelegate = (AppShellDelegate) appShell;
this.app = appDelegate.appShell;
}
else if ( appShell instanceof AppShell ) {
this.app = (AppShell) appShell;
if ( app.delegates.length > 0 )
this.appDelegate = app.delegates[0];
else
throw new SysException("Invalid AppShell/Delegate structure");
}
else
throw new SysException("Unsupported implementation of IAppShell: " + appShell.getClass().getName());
}
/**
* Get the component containing this task.
* @return the component containing this task.
*/
public ComponentClient getComponent() {
return component;
}
/**
* Tells if the run()-method of this Task is finished, but the Task is still active.
* This is normal behaviour with nonblocking pages.
*/
public boolean isRunfinished() {
return runfinished;
}
/**
* Marks the Task after its run()-method has finished.
* This method is resverved for the runtime. Do not call it directly!
*/
public void setRunfinished() {
runfinished=true;
}
/**
* Tells if this task will remove the submenu from its MenuItem in closeRequested.
* The default is true. To change this behaviour see {@link #setCleanSubmenu(boolean)}.
*/
public boolean isCleanSubmenu() {
return cleanSubmenu;
}
/**
* Determine if this task should remove the submenu from its MenuItem in closeRequested.
* @param cleanSubmenu true means remove it, false means do not change the menu while closing.
*/
public void setCleanSubmenu(boolean cleanSubmenu) {
this.cleanSubmenu = cleanSubmenu;
}
/**
* Tells if this task will automatically dispose the component started with {@link #callBlocking(IXMAControl)}
* or {@link #callNonBlocking(IXMAControl)}.
* @since 1.8.4
*/
public boolean isAutoDispose() {
return autoDispose;
}
/**
* Determine if this task should automatically dispose the component started with {@link #callBlocking(IXMAControl)}
* or {@link #callNonBlocking(IXMAControl)}.
* @param autoDispose true means dispose it after usage, false means to not dispose it automatically
* @since 1.8.4
*/
public void setAutoDispose(boolean autoDispose) {
this.autoDispose = autoDispose;
}
/**
* Returns the value of the autoClose-flag.
*/
public boolean isAutoClose () {
return autoClose;
}
/**
* Set the value of the autoClose-flag.
*/
public void setAutoClose ( boolean autoClose ) {
this.autoClose = autoClose;
}
}