/******************************************************************************* * Copyright (c) 2002-2006 Innoopract Informationssysteme 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: * Innoopract Informationssysteme GmbH - initial API and implementation ******************************************************************************/ package com.w4t; import java.util.ArrayList; import java.util.List; import org.apache.commons.fileupload.FileItem; import org.eclipse.rwt.internal.lifecycle.HtmlResponseWriter; import org.eclipse.rwt.internal.service.ContextProvider; import org.eclipse.rwt.internal.service.IServiceStateInfo; import org.eclipse.rwt.lifecycle.*; import com.w4t.IWindowManager.IWindow; import com.w4t.engine.util.FormManager; import com.w4t.engine.util.WindowManager; import com.w4t.event.WebFormEvent; import com.w4t.event.WebFormListener; import com.w4t.internal.adaptable.IFileUploadAdapter; import com.w4t.internal.adaptable.IFormAdapter; import com.w4t.types.WebColor; import com.w4t.types.WebTriState; import com.w4t.util.DefaultColorScheme; /** <p>WebForm is the root of a component-tree that represents the * html document as shown in the browser on the server. A W4Toolkit application * consists of one or more WebForms with user interface components (widgets) * that display information to the user and react to user action (like * mouse clicks etc.).</p> * * <p>A WebForm may open another WebForm in the * same window (see {@link W4TContext#dispatchTo(WebForm) * W4TContext#dispatchTo(WebForm)}), or open another WebForm in a new browser * window (see {@link W4TContext#showInNewWindow(WebForm) * W4TContext#showInNewWindow(WebForm)}). It usually contains widgets like * WebLabels, WebButtons etc.</p> * * <p>To design a WebForm, extend this class and implement the * abstract method {@link #setWebComponents() setWebComponents()}. * When the WebForm is created, setWebComponents() is called automatically. * </p> * <p>For example:<pre> * public class MyWebForm extends WebForm { * * private WebLabel label; * * protected void setWebComponents() throws Exception { * label = new WebLabel(); * label.setValue( "Hello World" ); * } * } * </pre></p> * * <p>For more information on how to place components on a WebForm * and how to arrange them using layout managers, see {@link * org.eclipse.rwt.WebContainer WebContainer}.</p> * * <p>WebForm instances are not created with the new-Operator, * but must be loaded with the factory method {@link * W4TContext#loadForm(String) W4TContext.loadForm(String)} * instead. Thus obtaining a WebForm instance works like this:</p> * * <p><pre> * // create an instance of MyForm and register it with the W4T System * WebForm form = W4TContext.loadForm( "com.mycorp.w4tapp.MyForm" ); * // cast into a MyForm, if needed * MyForm myForm = ( MyForm )form; * </pre></p> */ public abstract class WebForm extends WebContainer { /** <p>A reference to this WebForm (for use in anonymous event * listener classes).</p> */ public final WebForm self = this; private boolean multipartFormEncoding = false; /** a counter which enshures, that only the latest rendering * of this WebForm can send data to the WebComponents of the form */ private int requestCounter = 0; /** id of the WebComponent of this form which gets the focus */ private String focusID = ""; /** flag, which tells if the WebForm is currently shown in a browser */ private boolean active = false; /** the special timeout for closing this WebForm, overrides the standard * closing timeout for forms as set in the configuration file */ private long closingTimeout = -1; /** contains all css files set to this WebForm, which appear in the * render output as "link rel" tag.*/ private List cssFiles; /** tells whether the browsers navigation buttons are * enabled for this WebForm */ private boolean enableBrowserNavigation = false; private String windowOpenerBuffer = ""; private String windowRefresherBuffer = ""; private String windowCloserBuffer = ""; /** milliseconds since the WebForm's last rendering */ private long timeStamp; // window handling attributes ///////////////////////////// /** flag: whether the browser window containing this WebForm * will be refreshed */ private boolean refreshWindow = false; /** flag: whether this WebForm is opened in a new browser window */ private boolean showInNewWindow = false; /** a properties class which encapsulates information for the * browser instance, if this WebForm is shown in a new window */ private WindowProperties windowProperties = null; /** flag: whether the position of the horizontal and vertical scrollbars in * the browser window which is displaying this WebForm is preserved * between renderings. If true, the scrollbars are set at the newly rendered * html page in the browser window to the same position as before the * rendering. */ private boolean autoScroll = true; /** the position (in pixels) of the horizontal scrollbar in the browser * window displaying this WebForm. */ private int scrollX = 0; /** the position (in pixels) of the horizontal scrollbar in the browser * window displaying this WebForm. */ private int scrollY = 0; /** the title of the window, in which this WebForm is to be displayed. */ private String windowTitle = ""; // body attributes ////////////////// /** <p>the background color of this WebForm.</p> */ private WebColor bgColor; /** <p>the global text color on this WebForm.</p> */ private WebColor textColor; /** left position of the forms layout manager */ private String leftmargin = "0"; /** top position of the forms layout manager */ private String topmargin = "0"; /** left border width to the forms layout managers table */ private String marginwidth = "0"; /** top border width of the forms to the layout managers table */ private String marginheight = "0"; // design time specific fields ////////////////////////////// private IFormAdapter formAdapter; /** <p>Used by the W4 Toolkit library to create a new instance of * this WebForm - in order to obtain an instance that is properly * initialised and registered with the system, use the factory method * {@link org.eclipse.rwt.W4TContext#loadForm(String) loadForm(String)} * instead.</p> */ public WebForm() { refreshTimeStamp(); cssFiles = new ArrayList( 4 ); String sBgColor = DefaultColorScheme.get( DefaultColorScheme.WEB_OBJECT_BG ); bgColor = new WebColor( sBgColor ); String sTextColor = DefaultColorScheme.get( DefaultColorScheme.WEB_FORM_TEXT ); textColor = new WebColor( sTextColor ); initWindowProperties(); } /** * inits the properties for the window in which this WebForm is * displayed, if it opens a new browser instance. */ private void initWindowProperties() { windowProperties = new WindowProperties(); windowProperties.setLocation( new WebTriState( "no" ) ); windowProperties.setMenubar( new WebTriState( "no" ) ); windowProperties.setToolbar( new WebTriState( "no" ) ); windowProperties.setStatus( new WebTriState( "no" ) ); windowProperties.setDirectories( "no" ); windowProperties.setDependent( "no" ); windowProperties.setResizable( new WebTriState( "yes" ) ); windowProperties.setScrollbars( new WebTriState( "yes" ) ); windowProperties.setStatus( new WebTriState( "yes" ) ); } /** returns a clone of this WebForm.<br> * For all elementary WebComponents, cloning will result in a deep copy, * shallow copying all fields, cloning property objects (i.e. all * subclasses of WebComponentProperties, like Style, WindowProperties * etc.), and in case the WebObject to clone is a WebContainer, also * cloning all WebComponents, if they were added to it using * WebContainer.add(), and the WebLayout, if it was set using * WebContainer.setWebLayout(). Fields containing external references to * Objects which are not added with one of those methods are set to null * in the cloned object. */ public Object clone() throws CloneNotSupportedException { WebForm result = ( WebForm )super.clone(); // inits result.requestCounter = 0; result.windowProperties = ( WindowProperties )this.windowProperties.clone(); result.bgColor = ( WebColor )this.bgColor.clone(); return result; } private void postRender() { increaseRequestCounter(); refreshTimeStamp(); } /** {@link #requestCounter requestCounter} */ private void increaseRequestCounter() { requestCounter++; } /** <p>the main entry point for initialisation code. This method is executed * when an instance of this WebForm is created. It will usually be * used to add and initialise widgets (see {@link org.eclipse.rwt.WebContainer * WebContainer} for more information about how to add WebComponents and * arrange them using layout managers.</p> * * @throws Exception whenever an Exception occurs during the * initialisation code. */ protected abstract void setWebComponents() throws Exception; /** * Unloads a this WebForm from session scope. */ public void unload() { // before unloading the form fire the closing event try { if( active ) { active = false; int webEventType = WebFormEvent.WEBFORM_CLOSING; WebFormEvent evt = new WebFormEvent( this, webEventType ); evt.processEvent(); } } finally { FormManager.remove( this ); WindowManager.removeAssociatedWindow( this ); } } /** * Adds the specified WebFormListener to receive webFormClosing * events of this WebForm. WebFormClosing Events occur when a * a browser window is closed of a external url is loaded * @param listener the WebFormListener */ public void addWebFormListener( final WebFormListener listener ) { WebFormEvent.addListener( this, listener ); } /** * removes the specified WebFormListener which receives * webFormClosing events of this WebForm. * WebFormClosing Events occur when a * a browser window is closed of a external url is loaded * @param listener the WebFormListener */ public void removeWebFormListener( final WebFormListener listener ) { WebFormEvent.removeListener( this, listener ); } /** * <p> * closes the browser window displaying this WebForm. * </p> * <p> * <strong>Note:</strong> The WebForm is <em>not</em> unloaded when closing * the window. * </p> */ public void closeWindow() { final IWindow window = W4TContext.getWindowManager().findWindow( this ); if( window != null ) { window.close(); W4TContext.getLifeCycle().addPhaseListener( new PhaseListener() { private static final long serialVersionUID = 1L; public void afterPhase( final PhaseEvent event ) { if( WindowManager.isClosed( window ) ) { WindowManager.getInstance().remove( window ); W4TContext.getLifeCycle().removePhaseListener( this ); } } public void beforePhase( final PhaseEvent event ) { } public PhaseId getPhaseId() { return PhaseId.RENDER; } } ); } } /** * <p> * Refreshes the browser window displaying this WebForm. * </p> * <p> * Usually it is not necessary to refresh the WebForm currently being * processed. But it might be necessary to refresh another form * that is shown in a popup window. * <p> * <strong>Note:</strong> The effect of any previous call to * {@link #closeWindow <code>closeWindow</strong>} will be overridden by * this method. * </p> */ public void refreshWindow() { IWindow window = WindowManager.getInstance().findWindow( this ); if( window == null ) { // TODO [rh] throw IllegalStateException window = WindowManager.getInstance().create( this ); } else if( WindowManager.isClosing( window ) ) { WindowManager.setClosing( window, false ); } this.refreshWindow = true; } /** * returns whether the browser window displaying this WebForm will * be refreshed */ public boolean isRefreshing() { return refreshWindow; } /** * returns whether this WebForm will be displayed in a new * browser window */ public boolean isOpeningNewWindow() { return showInNewWindow; } /** sets the window properties for this WebForm */ public void setWindowProperties( final WindowProperties windowProperties ) { this.windowProperties = windowProperties; } /** <p>returns the window properties for this WebForm.</p> */ public WindowProperties getWindowProperties() { return windowProperties; } /** <p>sets the background color for this WebForm.</p> * <p>Corresponds to the HTML attribute bgcolor of the tag * ‹body›.</p> * * @param bgColor specifies the chosen color. Can either be a * hexadecimal RGB-value (red/green/blue-value * of the color) or one of 16 color names (like * "black", "white", "red" etc.). */ public void setBgColor( final WebColor bgColor ) { this.bgColor = bgColor; } /** <p>gets the background color for this WebForm.</p> * <p>Corresponds to the HTML attribute bgcolor of the tag * ‹body›.</p> */ public WebColor getBgColor() { return bgColor; } /** <p>sets the global text color on this WebForm.</p> */ public void setTextColor( final WebColor textColor ) { this.textColor = textColor; } /** <p>returns the global text color on this WebForm.</p> */ public WebColor getTextColor() { return textColor; } private void refreshTimeStamp() { timeStamp = System.currentTimeMillis(); } /** sets, whether the position of the horizontal and vertical scrollbars in * the browser window which is displaying this WebForm is preserved * between renderings. If true, the scrollbars are set at the newly rendered * html page in the browser window to the same position as before the * rendering. */ public void setAutoScroll( final boolean autoScroll ) { this.autoScroll = autoScroll; } /** returns, whether the position of the horizontal and vertical scrollbars in * the browser window which is displaying this WebForm is preserved * between renderings. If true, the scrollbars are set at the newly rendered * html page in the browser window to the same position as before the * rendering. */ public boolean isAutoScroll() { return autoScroll; } /** * <p>Sets the position of the horizontal scrollbar of the browser window, * in which this WebForm is displayed (in pixels).</p> */ public void setScrollX( final int scrollX ) { this.scrollX = scrollX; } /** * <p>Returns the position of the horizontal scrollbars of the browser * window, in which this WebForm is displayed (in pixels).</p> */ public int getScrollX() { return scrollX; } /** * <p>Sets the position of the vertical scrollbar of the browser window, * in which this WebForm is displayed (in pixels).</p> */ public void setScrollY( final int scrollY ) { this.scrollY = scrollY; } /** * <p>Returns the position of the vertical scrollbar of the browser window, * in which this WebForm is displayed (in pixels).</p> */ public int getScrollY() { return scrollY; } /** <p>Sets the title of the window, in which this WebForm is * to be displayed.</p> */ public void setWindowTitle( final String windowTitle ) { this.windowTitle = windowTitle; } /** returns the title of the window, in which this WebForm is * to be displayed. */ public String getWindowTitle() { return windowTitle; } /** sets the id of the WebComponent of this form which gets the focus */ public void setFocusID( final String focusID ){ this.focusID = focusID; } /** gets the id of the WebComponent which gets the focus, * if not set returns id of this form */ public String retrieveFocusID() { return focusID; } /** left position of the form layout manager */ public void setLeftmargin( final String leftmargin ) { this.leftmargin = leftmargin; } /** left position of the form layout manager */ public String getLeftmargin() { return leftmargin; } /** top position of the form layout manager */ public void setTopmargin( final String topmargin ) { this.topmargin = topmargin; } /** top position of the form layout manager */ public String getTopmargin() { return topmargin; } /** left border width to the forms layout managers table */ public void setMarginwidth( final String marginwidth ){ this.marginwidth = marginwidth; } /** left border width to the forms layout managers table */ public String getMarginwidth(){ return marginwidth; } /** top border width of the forms to the layout managers table */ public void setMarginheight( final String marginheight ) { this.marginheight = marginheight; } /** top border width of the forms to the layout managers table */ public String getMarginheight() { return marginheight; } /** sets whether the browsers navigation buttons are * enabled for this WebForm */ public void setEnableBrowserNavigation( final boolean enableBrowserNavigation ) { this.enableBrowserNavigation = enableBrowserNavigation; } /** returns whether the browsers navigation buttons are * enabled for this WebForm */ public boolean isEnableBrowserNavigation() { return enableBrowserNavigation; } /** <p>Sets the special timeout, in ms, for closing this WebForm, * overrides the standard closing timeout for forms as set in the * configuration file.</p> * * <p>As long as a WebForm is opened in a browser (JavaScript enabled * only), the form will be triggered from time to time even if there is no * user action. This means neither the WebForm closing timeout is triggered, * nor the user session expires. After the user closes the window or * navigates to another form, the closing timout countdown starts. This * allows very short session timeouts, but having the user running long * sessions without bothering running into such a session timeout by e.g. * editing the content of a page to slowly.</p> * * <p>Note: the timeout is only an approxymately value, since it depends on a * cleanup thread running from time to time. So the shorter the timeout the * more inexact is the real trigger of the closing timeout relatively to * the timeout settings.</p> * * @param closingTimeout The value for closingTimeout must be at least 60.*/ public void setClosingTimeout( final long closingTimeout ) { if ( closingTimeout >= 60 ) { this.closingTimeout = closingTimeout; } } /** <p>returns the special timeout for closing this WebForm, overrides * the standard closing timeout for forms as set in the configuration * file.</p> */ public long getClosingTimeout() { return closingTimeout; } /** <p>sets the passed css files to this WebForm.</p> * <p>Note that the given <code>cssFiles</code> must not contain duplicate * entries.</p> * <p>A css file that is set to a WebForm is referenced in the HTML * output from a <link rel=stylesheet type="text/css"> tag. The * href attribute of this tag is set to what is set here.</p> */ public void setCssFile( final String[] cssFiles ) { List buffer = new ArrayList(); for( int i = 0; i < cssFiles.length; i++ ) { if( buffer.contains( cssFiles[ i ] ) ) { String text = "The parameter 'cssFiles' contains duplicate entries."; throw new IllegalArgumentException( text ); } buffer.add( cssFiles[ i ] ); } this.cssFiles.clear(); for( int i = 0; i < cssFiles.length; i++ ) { this.cssFiles.add( cssFiles[ i ] ); } } /** <p>Sets the passed css file to this WebForm at the specified index.</p> * <p>Note that duplicate entries are not allowed.</p> * <p>A css file that is set to a WebForm is referenced in the HTML * output from a <link rel=stylesheet type="text/css"> tag. The * href attribute of this tag is set to what is set here.</p> */ public void setCssFile( final int index, final String cssFile ) { int existingIndex = cssFiles.indexOf( cssFile ); if( existingIndex != -1 && existingIndex != index ) { String text = "The parameter 'cssFile' already exists in the list of cssFiles. " + "Duplicate entries are not allowed."; throw new IllegalArgumentException( text ); } cssFiles.set( index, cssFile ); } /** <p>returns the css files which were set to this WebForm.</p> * * <p>A css file that is set to a WebForm is referenced in the HTML * output from a <link rel=stylesheet type="text/css"> tag. The * href attribute of this tag is set to what is set here.</p> */ public String[] getCssFile() { String[] result = new String[ cssFiles.size() ]; cssFiles.toArray( result ); return result; } /** <p>returns the css file which was set to this WebForm at the * specified index.</p> * * <p>A css file that is set to a WebForm is referenced in the HTML * output from a <link rel=stylesheet type="text/css"> tag. The * href attribute of this tag is set to what is set here.</p> */ public String getCssFile( final int index ) { return ( String )cssFiles.get( index ); } /** <p>adds the passed css files to the css files already set to * this WebForm.</p> * <p>Note that duplicate entries will be ignored.</p> * <p>A css file that is set to a WebForm is referenced in the HTML * output from a <link rel=stylesheet type="text/css"> tag. The * href attribute of this tag is set to what is set here.</p> */ public void addCssFile( final String cssFile ) { if( !cssFiles.contains( cssFile ) ) { cssFiles.add( cssFile ); } } public Object getAdapter( final Class adapter ) { Object result = null; if( adapter == IFileUploadAdapter.class ) { result = createFileUploadAdapter(); } else if( adapter == IFormAdapter.class ) { result = getFormAdapter(); } else { result = super.getAdapter( adapter ); } return result; } private Object createFileUploadAdapter() { return new IFileUploadAdapter() { public void setFileItem( final FileItem newFileItem ) { } public boolean isMultipartFormEncoding() { return multipartFormEncoding; } public void setMultipartFormEncoding( final boolean encoding ) { multipartFormEncoding = encoding; } }; } private Object getFormAdapter() { if( formAdapter == null ) { formAdapter = new IFormAdapter() { private HtmlResponseWriter renderBuffer; private void init() { if( renderBuffer == null ) { renderBuffer = new HtmlResponseWriter(); renderBuffer.append( " The WebForm '" ); renderBuffer.append( getClass().getName() ); renderBuffer.append( "' could not be rendered." ); } } public void postRender() { IServiceStateInfo stateInfo = ContextProvider.getStateInfo(); this.renderBuffer = stateInfo.getResponseWriter(); init(); WebForm.this.postRender(); } public HtmlResponseWriter getRenderBuffer() { init(); refreshTimeStamp(); return renderBuffer; } public void increase() { increaseRequestCounter(); } public long getTimeStamp() { return timeStamp; } public void refreshTimeStamp() { WebForm.this.refreshTimeStamp(); } public int getRequestCounter() { return requestCounter; } public void updateRequestCounter( final int requestCounter ) { WebForm.this.requestCounter = requestCounter; } public void refreshWindow( final boolean refreshWindow ) { WebForm.this.refreshWindow = refreshWindow; } public void showInNewWindow( final boolean showInNewWindow ) { WebForm.this.showInNewWindow = showInNewWindow; } public void addWindowOpenerBuffer( final String windowOpenerBuffer ) { WebForm.this.windowOpenerBuffer = windowOpenerBuffer; } public String getWindowOpenerBuffer() { return windowOpenerBuffer; } public void addWindowRefresherBuffer( final String refresherBuffer ) { WebForm.this.windowRefresherBuffer = refresherBuffer; } public String getWindowRefresherBuffer() { return windowRefresherBuffer; } public void addWindowCloserBuffer( final String closerBuffer ) { WebForm.this.windowCloserBuffer = closerBuffer; } public String getWindowCloserBuffer() { return windowCloserBuffer; } public void setActive( final boolean active ) { WebForm.this.active = active; } public boolean isActive() { return active; } }; } return formAdapter; } }