// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client;
import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.WindowScrollListener;
import com.google.gwt.user.client.ui.DecoratedPopupPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import java.util.HashMap;
import java.util.Map;
/**
* Popup that shows a status message while an asynchronous request is
* happening.
*
*/
public class RpcStatusPopup extends DecoratedPopupPanel implements RpcListener {
// Map from method names to messages
private static final Map<String, String> statusMessages = initMessages();
// Label that shows the message for the current RPC
private final Label label = new Label();
// Number of active RPCs. The popup is shown iff this is positive.
private int activeRPCs = 0;
/**
* Initializes the LoadingPopup.
*/
public RpcStatusPopup() {
super(/* autoHide = */ false);
setStyleName("ode-RpcStatusMessage");
setWidget(label);
// Re-center the loading message when the window is resized.
// TODO(halabelson): Replace the deprecated methods
Window.addWindowResizeListener(new WindowResizeListener() {
@Override
public void onWindowResized(int width, int height) {
positionPopup(getOffsetWidth());
}
});
// Reposition the message to the top of the screen when the
// window is scrolled
// TODO(halabelson): get rid of the flashing on vertical scrolling
Window.addWindowScrollListener(new WindowScrollListener() {
@Override
public void onWindowScrolled(int scrollLeft, int scrollTop) {
positionPopup(getOffsetWidth());
}
});
// Position the popup before showing it to prevent flashing.
setPopupPositionAndShow(new PopupPanel.PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
positionPopup(offsetWidth);
}
});
}
/**
* Register a service proxy with the loading popup. The loading popup will
* listen to the RPCs on the service and show/hide itself automatically.
*
* @param service the service to monitor
*/
public void register(ExtendedServiceProxy<?> service) {
service.addRpcListener(this);
}
/**
* Unregister a service proxy with the loading popup.
*
* @param service the service to monitor
*/
public void unregister(ExtendedServiceProxy<?> service) {
service.removeRpcListener(this);
}
// RpcListener implementation
@Override
public void onStart(String method, Object... params) {
// TODO(user): This is very primitive in the case of multiple RPCs. The
// message of the RPC started last succeeds. Its message will stay active
// until all RPCs have finished or a new RPC starts.
String message = statusMessages.get(method);
label.setText(message != null ? message : MESSAGES.defaultRpcMessage());
// Clear error display
ErrorReporter.hide();
countRPCs(+1);
}
@Override
public void onFailure(String method, Throwable caught) {
countRPCs(-1);
}
@Override
public void onSuccess(String method, Object result) {
countRPCs(-1);
}
private void countRPCs(int i) {
activeRPCs += i;
if (activeRPCs > 0) {
show();
} else {
hide();
}
}
private void positionPopup(int offsetWidth) {
// make sure the popup is on-screen
// if the top of the window is scrolled off the screen
setPopupPosition(
(Window.getClientWidth() - offsetWidth) >> 1,
Window.getScrollTop());
}
private static Map<String, String> initMessages() {
Map<String, String> msgs = new HashMap<String, String>();
// RPC methods that show a "Saving..." message
String saving = MESSAGES.savingRpcMessage();
msgs.put("newProject", saving);
msgs.put("save", saving);
msgs.put("storeProjectSettings", saving);
msgs.put("storeUserSettings", saving);
// RPC methods that show a "Copying..." message
msgs.put("copyProject", MESSAGES.copyingRpcMessage());
// RPC methods that show a "Deleting..." message
String deleting = MESSAGES.deletingRpcMessage();
msgs.put("deleteFile", deleting);
msgs.put("deleteFiles", deleting);
msgs.put("deleteProject", deleting);
// RPC methods that show a "Packaging..." message
msgs.put("build", MESSAGES.packagingRpcMessage());
// All other RPC methods will show the default "Loading..." message.
return msgs;
}
}