/*
* RHQ Management Platform
* Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.coregui.client.components.upload;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.smartgwt.client.widgets.form.DynamicForm;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.Messages;
public class DynamicCallbackForm extends DynamicForm implements DynamicCallbackFormImplHost {
protected Messages MSG = CoreGUI.getMessages();
private static int frameIndex = 0;
private String frameName;
private Element synthesizedFrame;
private DynamicCallbackFormHandlerCollection formHandlers;
private static DynamicCallbackFormImpl impl = GWT.create(DynamicCallbackFormImpl.class);
public DynamicCallbackForm(String frameName) {
super();
this.frameName = frameName + (frameIndex++);
setTarget(this.frameName);
init();
}
@Override
protected void onAttach() {
super.onAttach();
}
private void init() {
if (frameName != null) {
// Create and attach a hidden iframe to the body element.
createFrame();
Document.get().getBody().appendChild(synthesizedFrame);
//
// Hook up the underlying iframe's onLoad event when attached to the DOM.
// Making this connection only when attached avoids memory-leak issues.
// The FormPanel cannot use the built-in GWT event-handling mechanism
// because there is no standard onLoad event on iframes that works across browsers.
impl.hookEvents(synthesizedFrame, this);
}
}
private void createFrame() {
// Attach a hidden IFrame to the form. This is the target iframe to which
// the form will be submitted. We have to create the iframe using innerHTML,
// because setting an iframe's 'name' property dynamically doesn't work on
// most browsers.
Element dummy = Document.get().createDivElement();
dummy.setInnerHTML("<iframe src=\"javascript:''\" name='" + frameName
+ "' style='position:absolute;width:0;height:0;border:0'>");
synthesizedFrame = dummy.getFirstChildElement();
}
@Override
public void submitForm() {
impl.submit(getAction(), synthesizedFrame);
super.submitForm();
}
public void onFrameLoad() {
UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
if (handler != null) {
onFrameLoadAndCatch(handler);
} else {
onFrameLoadImpl();
}
// Window.alert("Submission ready!");
}
private void onFrameLoadAndCatch(UncaughtExceptionHandler handler) {
try {
onFrameLoadImpl();
} catch (Throwable e) {
handler.onUncaughtException(e);
}
}
private void onFrameLoadImpl() {
if (formHandlers != null) {
// Fire onComplete events in a deferred command. This is necessary
// because clients that detach the form panel when submission is
// complete can cause some browsers (i.e. Mozilla) to go into an
// 'infinite loading' state. See issue 916.
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
formHandlers.fireOnComplete(DynamicCallbackForm.this, impl.getContents(synthesizedFrame));
}
});
}
}
@Override
public void destroy() {
if (synthesizedFrame != null) {
// Unhook the iframe's onLoad when detached.
impl.unhookEvents(synthesizedFrame);
// And remove it from the document.
Document.get().getBody().removeChild(synthesizedFrame);
synthesizedFrame = null;
}
super.destroy();
}
public synchronized void addFormHandler(DynamicFormHandler handler) {
if (formHandlers == null) {
formHandlers = new DynamicCallbackFormHandlerCollection();
}
formHandlers.add(handler);
}
public synchronized void pushFormHandler(DynamicFormHandler handler) {
if (formHandlers == null) {
formHandlers = new DynamicCallbackFormHandlerCollection();
}
formHandlers.add(0, handler);
}
public void removeFormHandler(DynamicFormHandler handler) {
if (formHandlers != null) {
formHandlers.remove(handler);
}
}
}