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

at.spardat.xma.component.ComponentClient 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
 *******************************************************************************/

package at.spardat.xma.component;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import at.spardat.enterprise.exc.INotification;
import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.appshell.ITask;
import at.spardat.xma.boot.component.IComponentListener;
import at.spardat.xma.boot.component.IRtXMASessionClient;
import at.spardat.xma.boot.component.NamedEvent;
import at.spardat.xma.page.NotificationBox;
import at.spardat.xma.page.PageClient;
import at.spardat.xma.rpc.RemoteCallClient;
import at.spardat.xma.rpc.RemoteReply;
import at.spardat.xma.security.XMAContext;
import at.spardat.xma.serializer.XmaInput;
import at.spardat.xma.serializer.XmaOutput;
import at.spardat.xma.session.XMASessionClient;

/**
 * Implents the clients specific aspects of a Component.
 * This includes the management of SWT-Resources like the Display and Images.
 *
 * @author s2877
 */
public abstract class ComponentClient extends Component implements IComponentClient {

    /** color used to mark input fields containing errors */
    public static RGB errorBackground = new RGB(255,255,200);

    /** color used to mark uneditable fields containing errors */
    public static RGB errorBackgroundUneditable = new RGB(245, 240, 205);

    /** The Display for all Pages in the Component */
    Display display;
    /** true if this Component had to create a new Display */
    boolean displayIsNew;

    /** contains all active Images in the Component
     *  used to dispose them when the Component is finished */
    private HashMap images = new HashMap();

    /** contains all active Colors in the Component
     *  used to dispose them when the Component is finished */
    private HashMap colors = new HashMap();

    /**
     * Contains Fonts that are owned by this component and
     * freed in dispose.
     */
    private HashMap fFonts;

    /** contains all event-listeners for this Component
     * all elements implement IComponentListener */
    private List listeners;

    /** contains the input and output values of this component */
    private Properties properties;

    /**
     * the page of which the pageComposite was passed to method {@link #invoke(Composite)}
     * this page is used to display exceptions thrown in component {@link #enter()}
     * or {@link #leave()} methods
     */
    private PageClient invokingPage;

    /**
     * Indicates that the state of the components page models may be out
     * of sync with respect to the servers state. This necessitates
     * that not deltas but the full state is transmitted in the
     * next server side event.
     */
    private boolean                 outOfSyncWithServer_;


    /** Id for Info-Icon */
    public static final short resInfoGif = 1;
    /** Id for Warning-Icon */
    public static final short resWarnGif = 2;
    /** Id for Error-Icon */
    public static final short resErrorGif = 3;
    /**
     * maximum Id reserved by the runtime. currently 100.
     * please use only ids greater than this for your own images.
     */
    public static final short lastResGif = 100;

    /** mapping of Icon-Ids to Rescource-URIs */
    HashMap imageResources = new HashMap();
    {
        imageResources.put(new Short(resInfoGif),"at/spardat/xma/page/message_info.gif");
        imageResources.put(new Short(resWarnGif),"at/spardat/xma/page/message_warning.gif");
        imageResources.put(new Short(resErrorGif),"at/spardat/xma/page/message_error.gif");
    }

    /**
     * Constructor just for test-purpose. This constructor is not intended to be called
     * from outside JUnit-Tests.
     */
    public ComponentClient () {
    }

    /**
     * Constructor of the Component. Creates the Display if necessary.
     * Registers this component with the session.
     *
     * @param session the XMASession this component belongs to
     * @param isStateless defines whether this component is stateless or not.
     */
    public ComponentClient (XMASessionClient session, boolean isStateless) {
        super (session, isStateless, false);
        display = Display.getCurrent();
        if(display==null) {
            displayIsNew=true;
            display = Display.getDefault();
        }
        // register at session
        getSession().registerComponent (this);
        
        // In the case that just 256 colors are available, set the errorBackground to yellow.
        // (Otherwise the errorBackground would be white.)
        int colorDepth = display.getDepth();
        if (colorDepth <= 8) {        
            errorBackground = display.getSystemColor(SWT.COLOR_YELLOW).getRGB();
        }        
    }


   /**
     * Adds a ComponentListner to the listeners of the component. All listeners
     * are notified of all property-changes and component-events.
     *
     * @param listener the new listener to register
     */
    public void addEventListener(IComponentListener listener) {
        if(listeners==null) listeners = new ArrayList(1);
        if(!listeners.contains(listener)) listeners.add(listener);
    }

    /**
     * Remove a ComponentListener form the listners of the component. This
     * ComponentListner will not be notified of propertiy-changes and component-events
     * any more.
     * @param listener the ComponentListener to remove
     */
    public void removeEventListener(IComponentListener listener) {
        if(listeners!=null) {
            listeners.remove(listener);
            if(listeners.size()==0) listeners=null;
        }
    }

    /**
      * Adds a PropertyChangeListener to the listeners of the component. All listeners
      * are notified of all property-changes.
      *
      * @param listener the new listener to register
      */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        if(listeners==null) listeners = new ArrayList(1);
        if(!listeners.contains(listener)) listeners.add(listener);
    }

    /**
     * Remove a PropertyChangeListener form the listners of the component. This
     * PropertyChangeListener will not be notified of propertiy-changes
     * any more.
     * @param listener the PropertyChangeListener to remove
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        if(listeners!=null) {
            listeners.remove(listener);
            if(listeners.size()==0) listeners=null;
        }
    }

    /**
     * Sets all properties of the component. This method completly
     * resets the set of properties of the component to the set given
     * as input.
     * If there are registered ComponentListeners, all ComponentListeners
     * are notifyed of each property-change.
     *
     * @param input the new set of properties
     */
    public void setProperties(Properties input) {
        ComponentProperty[] props = getPropDes();
        if(props!=null) {
            for(Iterator it = input.keySet().iterator();it.hasNext();) {
                String key = (String)it.next();
                ComponentProperty prop = getPropDes(key);
                if(prop!=null && prop.isIn()) {
                    prop.setValue(input.getProperty(key));
                } else { // property not input or not defined
                    //silently ignore
                }
            }
//            // clear missing properties
//            for(int i=0;i use old implementation
            if(listeners==null) {
                properties = input;
            } else {
                Properties oldprops = properties;
                properties = input;
                for(Iterator it=properties.keySet().iterator();it.hasNext();) {
                    String key = (String)it.next();
                    String value = properties.getProperty(key);
                    String oldValue = oldprops.getProperty(key);
                    if(value==null&& oldValue!=null || !value.equals(oldValue)) {
                        for(Iterator itt=listeners.iterator();itt.hasNext();) {
                            ((PropertyChangeListener)itt.next()).propertyChange(new PropertyChangeEvent(this,key,oldValue,value));
                        }
                    }
                }
                // notify deletes
                for(Iterator it=oldprops.keySet().iterator();it.hasNext();) {
                   String key = (String)it.next();
                   String value = properties.getProperty(key);
                   String oldValue = oldprops.getProperty(key);
                   if(value==null && oldValue!=null) {
                       for(Iterator itt=listeners.iterator();itt.hasNext();) {
                           ((PropertyChangeListener)itt.next()).propertyChange(new PropertyChangeEvent(this,key,oldValue,value));
                       }
                   }
               }
            }
        }
    }

    /**
     * Sets one property of the component.
     * If there are registered ComponentListeners and the value of the
     * property is differend from its old value, all ComponentListeners
     * are notifyed of the property-change.
     *
     * @param name the name of the property to change
     * @param value the new value of the property
     */
    public void setProperty(String name, String value) {
        ComponentProperty prop = getPropDes(name);
        if(prop!=null) {
            if(prop.isIn()) {
                prop.setValue(value);
            } else { // property is not an input property
                // silently ignore
            }
        } else {
            if(getPropDes()==null) { // no properties defined in guidesigner -> use old implementation
                if(properties==null) {
                    properties = new Properties();
                }
                String oldValue = properties.getProperty(name);
                properties.setProperty(name,value);
                notifyPropertyChange(name,oldValue,value);
            } else { // properties defined in guidesigner, but this property is missing
                // silently ignore
            }
        }
    }

    /**
     * Notifies all registerd PropertyChangeListeners of a property change.
     * The event is only fired if oldValue and value differ.
     * @param name The name of the property which changed
     * @param oldValue The old value of the property
     * @param value The new value of the property
     */
    protected void notifyPropertyChange(String name,Object oldValue,Object value) {
        if(listeners!=null && value!=oldValue) {
            if(value==null&&oldValue!=null || !value.equals(oldValue)) {
                for(Iterator it=listeners.iterator();it.hasNext();) {
                    ((PropertyChangeListener)it.next()).propertyChange(new PropertyChangeEvent(this,name,oldValue,value));
                }
            }
        }
    }


    /**
     * Gives the value of a property. If the property is not defined
     * null is returned.
     *
     * @param name the name of the property
     * @return the value of the named property
     */
    public String getProperty(String name) {
        ComponentProperty prop = getPropDes(name);
        if(prop!=null) {
            if(prop.isOut()) {
                return prop.getValue();
            } else { // property is not an output property
                // silently ignore
                return null;
            }
        } else {
            if(getPropDes()==null) { // no properties defined in guidesigner -> use old implementation
                if(properties!=null) {
                    return properties.getProperty(name);
                } else {
                    return null;
                }
            } else { // properties defined in guidesigner, but this property is missing
                // silently ignore
                return null;
            }
        }
    }

    /**
     * Gives all properties of the component.
     * @return the properties of the component.
     */
    public Properties getProperties() {
        ComponentProperty[] props = getPropDes();
        if(props!=null) {
            Properties out = new Properties();
            for(int i=0;i use old implementation
            if(properties!=null) {
                return properties;
            } else {
                return new Properties();
            }
        }
    }


    /**
     * Notifies all listeners of the named event.
     *
     * @param name the name of the event
     * @param value an optional value passed with the event
     */
    public void notifyEvent(String name, String value) {
        if(listeners!=null) {
            for(Iterator it=listeners.iterator();it.hasNext();) {
                Object listener = it.next();
                if(listener instanceof IComponentListener) {
                    ((IComponentListener)listener).event(new NamedEvent(this,name,value));
                }
            }
        }
    }

    /**
     * Notifies all listener that this component was closed.
     */
    public void notifyClosed() {
        if(listeners!=null) {
            for(Iterator it=listeners.iterator();it.hasNext();) {
                Object listener = it.next();
                if(listener instanceof IComponentListener) {
                    ((IComponentListener)listener).componentClosed(new EventObject(this));
                }
            }
        }
    }

    /**
     * Gets the Display used by all Pages in the Component. This Display allways
     * exists and is never null.
     *
     * @return the Display for all Pages in the Component.
     */
    public Display getDisplay() {
        return display;
    }

    /**
     * Registers an image under the given id. This image-id can be used
     * in tables and trees.
     * @param id the new id of the image.
     * @param resource a resource-string naming the image file.
     */
    public void registerImage(short id, String resource) {
        imageResources.put(new Short(id),resource);
    }

    /**
     * Get an Image by its ID.
     * The resource is loaded via the classloader which downloads the jar-file
     * containing the resource if necessary. If the Image is allready loaded,
     * the loaded Image will be returned.
     * The Images are stored internally in the Component and will be disposed
     * automatically when the Component is finished. Do not dispose the Image!
     *
     * @param id one of the static final int ids defined in this class.
     * @return the Image or null if the resource can not be found.
     */
    public Image getImage(short id) {
        String resource = (String)imageResources.get(new Short(id));
        if(resource!=null) {
            return getImage(resource);
        } else {
            return null;
        }
    }

    /**
     * Get an Image by naming its resource-file.
     * The resource is loaded via the classloader which downloads the jar-file
     * containing the resource if necessary. If the Image is allready loaded,
     * the loaded Image will be returned.
     * The Images are stored internally in the Component and will be disposed
     * automatically when the Component is finished. Do not dispose the Image!
     *
     * @param resource a resource-string naming the image file.
     * @return the Image or null if the resource can not be found.
     */
    public Image getImage(String resource) {
        Image image = (Image) images.get(resource);
        if (image == null) {
            InputStream in = this.getClass().getClassLoader().getResourceAsStream(resource);
            if(in!=null) {
                image = new Image(display, in);
                images.put(resource, image);
            }
        }
        return image;
    }

    /**
     * Get a Color by naming its red, green and blue values.
     * The Colors are stored internally in the Component and will be disposed
     * automatically when the Component is finished. Do not dispose the Color!
     *
     * @param red the red value of the color.
     * @param green the green value of the color.
     * @param blue the blue value of the color.
     * @return the Color corresponding to this values
     */
    public Color getColor(int red, int green, int blue) {
        return getColor(new RGB(red,green,blue));
    }

    /**
     * Get a Color by naming its red-green-blue value.
     * The Colors are stored internally in the Component and will be disposed
     * automatically when the Component is finished. Do not dispose the Color!
     *
     * @param rgb the red, green, blue values defining the color.
     * @return the Color corresponding to this values
     */
    public Color getColor(RGB rgb) {
        Color color = (Color) colors.get(rgb);
        if(color==null) {
            color = new Color(display,rgb);
            colors.put(rgb,color);
        }
        return color;
    }

    /**
     * Returns a font for the specified data that is owned by this component
     * and automatically disposed if this component is disposed. Do not
     * dispose the returned Font!
     *
     * @param name the name of the font (must not be null)
     * @param height the font height in points
     * @param style a bit or combination of SWT.NORMAL, SWT.BOLD, SWT.ITALIC
     * @return a font-object. Must not be disposed by the caller.
     */
    public Font getFont (String name, int height, int style) {
        FontDescriptor      fd = new FontDescriptor (name, height, style);
        if (fFonts == null) fFonts = new HashMap();
        Font                f = (Font) fFonts.get(fd);
        if (f == null) {
            f = new Font (display, name, height, style);
            fFonts.put(fd, f);
        }
        return f;
    }

    /**
     * Returns a font whose name and style is taken from template
     * and whose height is provided. Do not dispose the returned font.
     *
     * @param template the reference font. Must not be null.
     * @param height   the height in points of the return Font.
     * @return a font-object. Must not be disposed by the caller.
     */
    public Font getFontByHeight (Font template, int height) {
        if (template == null) throw new IllegalArgumentException();
        FontData        fData = template.getFontData()[0];
        return getFont (fData.getName(), height, fData.getStyle());
    }

    /**
     * Returns a font whose name and height is taken from template
     * and whose style is provided. Do not dispose the returned font.
     *
     * @param template the reference font. Must not be null.
     * @param style    the style of the font.
     * @return a font object. Must not be disposed by the caller.
     */
    public Font getFontByStyle (Font template, int style) {
        if (template == null) throw new IllegalArgumentException();
        FontData        fData = template.getFontData()[0];
        return getFont (fData.getName(), fData.getHeight(), style);
    }

    /**
     * Gets the URI to the help page explaining this component. The help page must be
     * showable inside a web browser.
     * This method is implemented in the generated Class for each ComponentClient.
     *
     * @return the uri of the help page.
     */
    public String getHelpUri() { return null; }


    /**
     * Frees all allocated recources of the Component.
     * This includes freeing all still living statefull PageModels at the server
     * and disposing all SWT-resources like Images.
     */
    public void dispose() {
        Collection models=new ArrayList(pageModels.values());
        for(Iterator it=models.iterator();it.hasNext();) {
            ((PageClient)it.next()).removeModel();
        }
        pageModels.clear();

        for (Iterator it = images.values().iterator(); it.hasNext();) {
            ((Image) it.next()).dispose();
        }
        images.clear();
        for (Iterator it = colors.values().iterator(); it.hasNext();) {
            ((Color) it.next()).dispose();
        }
        colors.clear();

        // dispose fonts
        if (fFonts != null) {
            for (Iterator it = fFonts.values().iterator(); it.hasNext();) {
                ((Font)it.next()).dispose();
            }
            fFonts.clear();
        }

//        if(displayIsNew) {
//            display.dispose();
//            display=null;
//        }

        /**
         * deregister at session
         */
        getSession().removeComponent(this);
        getSession().getAppContainer().getAppManager().endComponent(this);
    }


    /**
     * Frees the Page with the given ID.
     * The Page will also be freed on the server bevor the next
     * serverEvent is executed. If the Page does not exist or
     * is allredy freed, nothing happens.
     *
     * @param idPageModel the ID of the Page to destroy.
     */
    public void freePageModel(short idPageModel) {
        pageModels.remove(new Integer(idPageModel));
    }


    /**
     * This Method is called by the Launcher to start the Component on the
     * client side. Before guidesigner 3.4.1.1, there was a first cut generation
     * of this method in the derived component class. Since guidesigner 3.4.1.1,
     * this method is generated into the generated base class of the component and
     * contains calls to modeled init functions of component and page. Since guidesigner 3.5.3,
     * it additionally contains calls of the life cycle methods {@link #enter()} and
     * {@link #leave()}, if the property doUseComponentLifeCycleMethods=true
     * is set in guidesign.properties.
     * This Method can be overwritten by the application programmer. Do not forget
     * to call super if you want to use modeled initialization or life cycle
     * methods of the component.
     */
    abstract public void invoke(Composite parent);

    /**
     * This method calculates the data stream necessary to update the server side
     * component so that its state equals this client side component.
     *
     * @param forceFull the meaning here is as follows: If forceFull, we do
     *                   not trust the delta mechanism. That implies that all alive
     *                   pages are transmitted with all their widget models. So the
     *                   server side state of the component may be deliberately inconsistent
     *                   before. If forceFull is false, only changed pages or stateless pages
     *                   are transmitted.
     *
     * @see at.spardat.xma.mdl.Synchronization#externalize(at.spardat.xma.serializer.XmaOutput, boolean)
     */
    public void externalize (XmaOutput xo, boolean forceFull) throws IOException {
        // write properties
        externalizeProperties (xo, forceFull);
        // write boolean to indicate if stream is full or delta
        xo.writeBoolean("full", forceFull);
        if (forceFull) externalizeFull (xo);
        else           externalizeDeltas (xo);
    }

    /**
     * Assumes that the server side components state is correct with respect to the
     * intention that accumulated changes in all models may be safely applied to it.
     * Then this method writes the delta information neccessary to update the
     * server side component state in order to make it equal to this.
     */
    private void externalizeDeltas (XmaOutput xo) throws IOException {
        // we build three sets; the first is the set of alive models at the client
        // that are not new and stateless
        HashSet           pOldStateless = new HashSet();
        // client alive models that are not new and stateful
        HashSet           pOldStateful = new HashSet();
        // the third set covers the new models
        HashSet           pNew = new HashSet();
        // the union of the these sets represents the programmer visible alive page models
        // at the client before the server side event
        Iterator          iter = getPageModels();
        while (iter.hasNext()) {
            PageClient          p = (PageClient) iter.next();
            if (p.hasModels()) {
                if (p.isNew()) pNew.add(p);
                else {
                    if (p.isStateless()) pOldStateless.add(p);
                    else                 pOldStateful.add(p);
                }
            }
        }

        /**
         * Write header information; this information is necessary for the server to
         * adjust the set of alive pages.
         */
        // old stateless pages must be created at the server --> long header
        xo.writeShort("numOldStateless", pOldStateless.size());
        iter = pOldStateless.iterator();
        while (iter.hasNext()) {
            writeLongHeader((PageClient) iter.next(), xo);
        }
        // old stateful pages must already exist at the server --> short header
        xo.writeShort("numOldStateful", pOldStateful.size());
        iter = pOldStateful.iterator();
        while (iter.hasNext()) {
            writeShortHeader((PageClient) iter.next(), xo);
        }
        // new pages must be created at the server --> long header
        xo.writeShort("numNew", pNew.size());
        iter = pNew.iterator();
        while (iter.hasNext()) {
            writeLongHeader((PageClient) iter.next(), xo);
        }


        // out of the set (pOldStateful union pOldStateless union pNew), write the page data
        // that really changed
        HashSet             all = new HashSet();
        all.addAll(pNew);
        all.addAll(pOldStateful);
        all.addAll(pOldStateless);
        externalizePageSet (all, xo, false);
    }

    // writes only the id of the page
    private void writeShortHeader (PageClient p, XmaOutput xo) throws IOException {
        xo.writeShort("id", p.getId());
    }

    // writes the id, the parent id and the typeId.
    // Necessary for pages which have to be created at the server
    private void writeLongHeader (PageClient p, XmaOutput xo) throws IOException {
        xo.writeShort("id", p.getId());
        PageClient      parent = p.getParent();
        short parentId = (parent == null ? -1 : parent.getId());
        xo.writeShort("parntId", parentId);
        xo.writeShort("typeid", p.getTypeId());
    }

    /**
     * Here, we do not rely on any state the server component has. All models alive with
     * all their data is transmitted.
     */
    private void externalizeFull (XmaOutput xo) throws IOException {
        // collect the all alive pages
        HashSet           pages = new HashSet();
        Iterator          iter = getPageModels();
        while (iter.hasNext()) {
            PageClient          p = (PageClient) iter.next();
            if (p.hasModels()) {
                pages.add(p);
            }
        }
        // write header information for every page
        xo.writeShort("numPages", pages.size());
        iter = pages.iterator();
        while (iter.hasNext()) {
            writeLongHeader ((PageClient)iter.next(), xo);
        }

        // fully write these pages
        externalizePageSet (pages, xo, true);
    }

    /**
     * This method gets the data stream after a server side event and applies
     * the changes to this client side component.
     *
     * @see at.spardat.xma.mdl.Synchronization#internalize(at.spardat.xma.serializer.XmaInput)
     */
    public void internalize (XmaInput in) throws IOException, ClassNotFoundException {
        // properties
        internalizeProperties(in);
        // pages
        internalizePageSet(in);
    }

    /**
     * Returns the global context.
     * @return XMAContext
     */
    public XMAContext getContext() {
        return session_.getContext();
    }

    /**
     * Returns the Session this belongs to (you can rely on the returned object not to be null).
     */
    public XMASessionClient getSession () {
        return (XMASessionClient) session_;
    }

    /**
     * Returns the Session this belongs to (you can rely on the returned object not to be null).
     */
    public IRtXMASessionClient getRTSession () {
        return (IRtXMASessionClient) session_;
    }


    /**
     * Returns if the clients page model state is out of sync with respect to
     * the servers state. 

* This method must not be called or overwritten outside the framework. */ public boolean isOutOfSyncWithServer() { return outOfSyncWithServer_; } /** * Sets the out of sync state.

* This method must not be called or overwritten outside the framework. */ public void setOutOfSyncWithServer(boolean b) { outOfSyncWithServer_ = b; } /** * Constructs a {@link at.spardat.xma.rpc.RemoteCall RemoteCall} object to execute a * server side method with the provided name. The corresponding server side Component * class must have a method with the signature *

     * void <namEvent> (RemoteCall call, RemoteReply reply)
     * 
* This method will be called if you call execute on the RemoteCall * object returned by this. * * @param namEvent the name of the server side method to call * @return a RemoteCall object */ protected RemoteCallClient newRemoteCall (String namEvent) { return new RemoteCallClient (this, namEvent); } /** * Displays the provided notification in a modal message box. * * @return A reaction constant of the class INotification, this is one of the constants * starting with praefix R_ and indicates the pressed push button on the * message dialogue. */ public int showMessage (INotification notification) { boolean disposeShell = false; Shell shell = null; try { // find a suitable shell if(shell==null) shell = getDisplay().getActiveShell(); if(shell==null) { shell = new Shell (getDisplay()); disposeShell = true; } // show the box return NotificationBox.show (notification, shell, getContext(), getSession()); } finally { if(disposeShell) { shell.dispose();} } } /** * Used as key in the HashMap of fonts. */ private static class FontDescriptor { String fName; int fHeight; int fStyle; public FontDescriptor (String name, int height, int style) { fName = name; fHeight = height; fStyle = style; } /** * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals (Object obj) { FontDescriptor fdOther = (FontDescriptor)obj; return fName.equals(fdOther.fName) && fHeight == fdOther.fHeight && fStyle == fdOther.fStyle; } /** * @see java.lang.Object#hashCode() */ public int hashCode() { return fName.hashCode() ^ fHeight ^ fStyle; } } /** * Creates the Task with the given name. The default implementation * takes the name as the fully qualified classname of the Task. * @param name unique name for the task within the component. * @since 1.4.0 */ public ITask createTask(String name) { try { Constructor con = Class.forName(name).getConstructor(new Class[]{ComponentClient.class}); return (ITask) con.newInstance(new Object[] {this}); } catch (InvocationTargetException e) { throw new SysException(e.getTargetException()); } catch (Exception e) { throw new SysException(e); } } /** * Is called at the end of RemoteCallClient.execute(). May be overwritten * by subclasses to implement some RPC-post processing. Is not called, * if the RPC terminates with exceptions. * * @param rc the RemoteCallClient whose execute method is about to end * @param reply the RemoteReply object that execute will return */ public void rpcFinished (RemoteCallClient rc, RemoteReply reply) { } /** * Stores the page of the given parentComposite for using in exception handling. * Exceptions thrown in component {@link #enter()} or {@link #leave()} methods * are shown using this page * @param parentComposite used to determine its corresponding page. * May be null; in this case no page is stored. * @since 2.2.0 */ protected void setInvokingPage(Composite parentComposite) { invokingPage=(PageClient) parentComposite.getData(); } /** * Notify the Component, that {@link #invoke(Composite)} is called. * @since 2.2.0 */ protected void enterBaseInvoke() { try { enter(); } catch (Exception exc) { showException(exc); } } /** * This method will be called by the generated method {@link #invoke(Composite)} * before any page is invoked. * It can be overwritten for some initializations. * @since 2.2.0 */ protected void enter() {} /** * Notify the Component, that {@link #invoke(Composite)} is finished. * @since 2.2.0 */ protected void leaveBaseInvoke() { try { leave(); } catch (Exception exc) { showException(exc); } } /** * This method will be called by the generated method {@link #invoke(Composite)} * after the invocation of the page is finished. * It can be overwritten for some cleanups. * @since 2.2.0 */ protected void leave() {} /** * Shows the given exception. If {@link #invokingPage} is not null, * it is used to show the exception. * @since 2.2.0 */ private void showException(Exception exc) { if(invokingPage!=null) { invokingPage.showException(exc); } else { PageClient.showExceptionImpl(exc,null,this); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy