All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.spardat.xma.appshell.Task Maven / Gradle / Ivy

There is a newer version: 6.0.2
Show newest version
/*******************************************************************************
 * 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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy