// -*- 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 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.HTML;
import com.google.gwt.user.client.ui.PopupPanel;
/**
* This class is used to display popup error messages along the center
* top edge of the UI. It can also display the messages in an
* alternate CSS style, so they can serve as information messages, as
* opposed to error messages.
*
* @author halabelson@google.com (Hal Abelson)
*/
public final class ErrorReporter {
/**
* Popup that shows error or info messages
*/
// Styles for error and info messages. These are defined in Ya.css
private static final String ERROR_SPAN_ENCLOSER_START = "<span class=\"ode-ErrorMessage\">";
private static final String INFO_SPAN_ENCLOSER_START = "<span class=\"ode-InfoMessage\">";
private static final String SPAN_ENCLOSER_END = "</span>";
private static class ErrorPopup extends PopupPanel {
// Label holding error message
private final HTML messageLabel;
/**
* Initializes the ErrorPopup.
*/
ErrorPopup() {
super(true); //constructor for PopupPanel class. "True" initializes the "auto-hide" variable
// I'm leaving this setSTyleName line here as a comment, to show the typical way to define
// the style.
// I would have preferred to use this method rather than constructing the HTML by hand,
// but it seems that GWT doesn't let the StyleName to be switched dynamically.
// setStyleName("ode-ErrorMessage");
messageLabel = new HTML();
setWidget(messageLabel);
// Recenter the message when the window is resized.
// TODO(halabelson): replace the deprecated methods
Window.addWindowResizeListener(new WindowResizeListener() {
@Override
public void onWindowResized(int width, int height) {
centerTopPopup();
}
});
// 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) {
centerTopPopup();
}
});
}
/**
* Sets the message to be shown
*
* @param message message
*/
void setMessageHTML(String message) {
messageLabel.setHTML(message);
}
/*
* Centers the popup along the top edge of the UI.
*/
private void centerTopPopup() {
setPopupPosition(
// make sure the popup is on-screen
// if the top of the window is scrolled off the screen
(Window.getClientWidth() - getOffsetWidth()) / 2,
Window.getScrollTop());
}
}
// Singleton instance of the popup
private static final ErrorPopup POPUP = new ErrorPopup();
private static void reportMessage(String message) {
if (!Ode.isWindowClosing()) {
POPUP.setMessageHTML(message);
// Position the popup before showing it to prevent flashing.
POPUP.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
POPUP.centerTopPopup();
}
});
}
}
/**
* Reports an error along the top edge center of the UI.
*
* @param message error message
*/
public static void reportError(String message) {
reportMessage(ERROR_SPAN_ENCLOSER_START + message + SPAN_ENCLOSER_END);
}
/**
* Reports information along the top edge center of the UI.
*
* @param message information message
*/
// The reportInfo methods overloads the error message system to display messages that
// aren't errors. This is a bit of a hack, but it's convenient because it guarantees
// that the information messages won't collide with error messages.
public static void reportInfo(String message) {
reportMessage(INFO_SPAN_ENCLOSER_START + message + SPAN_ENCLOSER_END);
}
/**
* Hides the error popup.
*/
public static void hide() {
if (!Ode.isWindowClosing()) {
POPUP.hide();
}
}
}