aboutsummaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorHenri Sara <henri.sara@itmill.com>2010-05-25 06:49:12 +0000
committerHenri Sara <henri.sara@itmill.com>2010-05-25 06:49:12 +0000
commitbf0b3fb23cdced41e7627107ea9d2536f9b428a6 (patch)
tree9b1186af571c6c933b875a123f683dc643a1ee23 /src/com
parent058495a1c5ec03eaca57c522d9c9976f676c0337 (diff)
parent06f72ea079f5a91181652b432fd7b10b489d4ca2 (diff)
downloadvaadin-framework-bf0b3fb23cdced41e7627107ea9d2536f9b428a6.tar.gz
vaadin-framework-bf0b3fb23cdced41e7627107ea9d2536f9b428a6.zip
Merged changes to 6.4
svn changeset:13340/svn branch:6.4
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/launcher/DevelopmentServerLauncher.java24
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java291
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java11
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java92
-rw-r--r--src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java6
-rw-r--r--src/com/vaadin/ui/GridLayout.java8
-rw-r--r--src/com/vaadin/ui/TabSheet.java79
7 files changed, 435 insertions, 76 deletions
diff --git a/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/src/com/vaadin/launcher/DevelopmentServerLauncher.java
index ef02f8817f..b7caa881b1 100644
--- a/src/com/vaadin/launcher/DevelopmentServerLauncher.java
+++ b/src/com/vaadin/launcher/DevelopmentServerLauncher.java
@@ -21,7 +21,7 @@ import com.vaadin.launcher.util.BrowserLauncher;
*/
public class DevelopmentServerLauncher {
- private final static String serverPort = "8888";
+ private final static int serverPort = 8888;
/**
* Main function for running Jetty.
@@ -59,6 +59,18 @@ public class DevelopmentServerLauncher {
protected static String runServer(Map<String, String> serverArgs,
String mode) {
+ // Assign default values for some arguments
+ assignDefault(serverArgs, "webroot", "WebContent");
+ assignDefault(serverArgs, "httpPort", "" + serverPort);
+ assignDefault(serverArgs, "context", "");
+
+ int port = serverPort;
+ try {
+ port = Integer.parseInt(serverArgs.get("httpPort"));
+ } catch (NumberFormatException e) {
+ // keep default value for port
+ }
+
// Add help for System.out
System.out
.println("-------------------------------------------------\n"
@@ -69,17 +81,12 @@ public class DevelopmentServerLauncher {
+ serverPort
+ "\n-------------------------------------------------\n");
- // Assign default values for some arguments
- assignDefault(serverArgs, "webroot", "WebContent");
- assignDefault(serverArgs, "httpPort", serverPort);
- assignDefault(serverArgs, "context", "");
-
try {
final Server server = new Server();
final Connector connector = new SelectChannelConnector();
- connector.setPort(8888);
+ connector.setPort(port);
server.setConnectors(new Connector[] { connector });
final WebAppContext webappcontext = new WebAppContext();
@@ -97,8 +104,7 @@ public class DevelopmentServerLauncher {
return null;
}
- return "http://localhost:" + serverArgs.get("httpPort")
- + serverArgs.get("context");
+ return "http://localhost:" + port + serverArgs.get("context");
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java
index 56de379988..32b2323f95 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java
@@ -48,6 +48,7 @@ import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VTooltip;
/**
+ * Client side implementation of the Select component.
*
* TODO needs major refactoring (to be extensible etc)
*/
@@ -55,12 +56,21 @@ public class VFilterSelect extends Composite implements Paintable, Field,
KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler,
Focusable {
+ /**
+ * Represents a suggestion in the suggestion popup box
+ */
public class FilterSelectSuggestion implements Suggestion, Command {
private final String key;
private final String caption;
private String iconUri;
+ /**
+ * Constructor
+ *
+ * @param uidl
+ * The UIDL recieved from the server
+ */
public FilterSelectSuggestion(UIDL uidl) {
key = uidl.getStringAttribute("key");
caption = uidl.getStringAttribute("caption");
@@ -70,6 +80,11 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Gets the visible row in the popup as a HTML string. The string
+ * contains an image tag with the rows icon (if an icon has been
+ * specified) and the caption of the item
+ */
public String getDisplayString() {
final StringBuffer sb = new StringBuffer();
if (iconUri != null) {
@@ -81,23 +96,43 @@ public class VFilterSelect extends Composite implements Paintable, Field,
return sb.toString();
}
+ /**
+ * Get a string that represents this item. This is used in the text box.
+ */
public String getReplacementString() {
return caption;
}
+ /**
+ * Get the option key which represents the item on the server side.
+ *
+ * @return The key of the item
+ */
public int getOptionKey() {
return Integer.parseInt(key);
}
+ /**
+ * Get the URI of the icon. Used when constructing the displayed option.
+ *
+ * @return
+ */
public String getIconUri() {
return iconUri;
}
+ /**
+ * Executes a selection of this item.
+ */
public void execute() {
onSuggestionSelected(this);
}
}
+ /**
+ * Represents the popup box with the selection options. Wraps a suggestion
+ * menu.
+ */
public class SuggestionPopup extends VOverlay implements PositionCallback,
CloseHandler<PopupPanel> {
@@ -117,6 +152,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
private int topPosition;
+ /**
+ * Default constructor
+ */
SuggestionPopup() {
super(true, false, true);
menu = new SuggestionMenu();
@@ -138,6 +176,16 @@ public class VFilterSelect extends Composite implements Paintable, Field,
addCloseHandler(this);
}
+ /**
+ * Shows the popup where the user can see the filtered options
+ *
+ * @param currentSuggestions
+ * The filtered suggestions
+ * @param currentPage
+ * The current page number
+ * @param totalSuggestions
+ * The total amount of suggestions
+ */
public void showSuggestions(
Collection<FilterSelectSuggestion> currentSuggestions,
int currentPage, int totalSuggestions) {
@@ -186,8 +234,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
- private void setNextButtonActive(boolean b) {
- if (b) {
+ /**
+ * Should the next page button be visible to the user?
+ *
+ * @param active
+ */
+ private void setNextButtonActive(boolean active) {
+ if (active) {
DOM.sinkEvents(down, Event.ONCLICK);
DOM.setElementProperty(down, "className", CLASSNAME
+ "-nextpage");
@@ -198,8 +251,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
- private void setPrevButtonActive(boolean b) {
- if (b) {
+ /**
+ * Should the previous page button be visible to the user
+ *
+ * @param active
+ */
+ private void setPrevButtonActive(boolean active) {
+ if (active) {
DOM.sinkEvents(up, Event.ONCLICK);
DOM
.setElementProperty(up, "className", CLASSNAME
@@ -212,6 +270,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
+ /**
+ * Selects the next item in the filtered selections
+ */
public void selectNextItem() {
final MenuItem cur = menu.getSelectedItem();
final int index = 1 + menu.getItems().indexOf(cur);
@@ -230,6 +291,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Selects the previous item in the filtered selections
+ */
public void selectPrevItem() {
final MenuItem cur = menu.getSelectedItem();
final int index = -1 + menu.getItems().indexOf(cur);
@@ -257,6 +321,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
+ * .user.client.Event)
+ */
@Override
public void onBrowserEvent(Event event) {
final Element target = DOM.eventGetTarget(event);
@@ -270,6 +341,15 @@ public class VFilterSelect extends Composite implements Paintable, Field,
tb.setFocus(true);
}
+ /**
+ * Should paging be enabled. If paging is enabled then only a certain
+ * amount of items are visible at a time and a scrollbar or buttons are
+ * visible to change page. If paging is turned of then all options are
+ * rendered into the popup menu.
+ *
+ * @param paging
+ * Should the paging be turned on?
+ */
public void setPagingEnabled(boolean paging) {
if (isPagingEnabled == paging) {
return;
@@ -370,6 +450,8 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
/**
+ * Was the popup just closed?
+ *
* @return true if popup was just closed
*/
public boolean isJustClosed() {
@@ -377,6 +459,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
return (lastAutoClosed > 0 && (now - lastAutoClosed) < 200);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google
+ * .gwt.event.logical.shared.CloseEvent)
+ */
public void onClose(CloseEvent<PopupPanel> event) {
if (event.isAutoClosed()) {
lastAutoClosed = (new Date()).getTime();
@@ -399,8 +488,14 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
+ /**
+ * The menu where the suggestions are rendered
+ */
public class SuggestionMenu extends MenuBar {
+ /**
+ * Default constructor
+ */
SuggestionMenu() {
super(true);
setStyleName(CLASSNAME + "-suggestmenu");
@@ -418,6 +513,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Sets the suggestions rendered in the menu
+ *
+ * @param suggestions
+ * The suggestions to be rendered in the menu
+ */
public void setSuggestions(
Collection<FilterSelectSuggestion> suggestions) {
clearItems();
@@ -446,6 +547,10 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Send the current selection to the server. Triggered when a selection
+ * is made or on a blur event.
+ */
public void doSelectedItemAction() {
// do not send a value change event if null was and stays selected
final String enteredItemValue = tb.getText();
@@ -472,6 +577,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Triggered after a selection has been made
+ */
public void doPostFilterSelectedItemAction() {
final MenuItem item = getSelectedItem();
final String enteredItemValue = tb.getText();
@@ -532,6 +640,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
suggestionPopup.hide();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.ui.MenuBar#onBrowserEvent(com.google
+ * .gwt.user.client.Event)
+ */
@Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONLOAD) {
@@ -556,7 +671,17 @@ public class VFilterSelect extends Composite implements Paintable, Field,
private final FlowPanel panel = new FlowPanel();
+ /**
+ * The text box where the filter is written
+ */
private final TextBox tb = new TextBox() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.TextBoxBase#onBrowserEvent(com.google
+ * .gwt.user.client.Event)
+ */
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -568,7 +693,17 @@ public class VFilterSelect extends Composite implements Paintable, Field,
private final SuggestionPopup suggestionPopup = new SuggestionPopup();
+ /**
+ * Used when measuring the width of the popup
+ */
private final HTML popupOpener = new HTML("") {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
+ * .user.client.Event)
+ */
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -633,6 +768,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
private boolean focused = false;
private int horizPaddingAndBorder = 2;
+ /**
+ * Default constructor
+ */
public VFilterSelect() {
selectedItemIcon.setStyleName("v-icon");
selectedItemIcon.addLoadHandler(new LoadHandler() {
@@ -674,6 +812,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
popupOpener.addClickHandler(this);
}
+ /**
+ * Does the Select have more pages?
+ *
+ * @return true if a next page exists, else false if the current page is the
+ * last page
+ */
public boolean hasNextPage() {
if (totalMatches > (currentPage + 1) * pageLength) {
return true;
@@ -682,10 +826,25 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Filters the options at a certain page. Uses the text box input as a
+ * filter
+ *
+ * @param page
+ * The page which items are to be filtered
+ */
public void filterOptions(int page) {
filterOptions(page, tb.getText());
}
+ /**
+ * Filters the options at certain page using the given filter
+ *
+ * @param page
+ * The page to filter
+ * @param filter
+ * The filter to apply to the components
+ */
public void filterOptions(int page, String filter) {
if (filter.equals(lastFilter) && currentPage == page) {
if (!suggestionPopup.isAttached()) {
@@ -711,6 +870,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
currentPage = page;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
+ * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
+ */
@SuppressWarnings("deprecation")
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
paintableId = uidl.getId();
@@ -861,6 +1027,10 @@ public class VFilterSelect extends Composite implements Paintable, Field,
initDone = true;
}
+ /**
+ * Turns prompting on. When prompting is turned on a command prompt is shown
+ * in the text box if nothing has been entered.
+ */
private void setPromptingOn() {
if (!prompting) {
prompting = true;
@@ -869,6 +1039,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
tb.setText(inputPrompt);
}
+ /**
+ * Turns prompting off. When prompting is turned on a command prompt is
+ * shown in the text box if nothing has been entered.
+ *
+ * @param text
+ * The text the text box should contain.
+ */
private void setPromptingOff(String text) {
tb.setText(text);
if (prompting) {
@@ -877,6 +1054,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Triggered when a suggestion is selected
+ *
+ * @param suggestion
+ * The suggestion that just got selected.
+ */
public void onSuggestionSelected(FilterSelectSuggestion suggestion) {
selecting = false;
@@ -906,6 +1089,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
suggestionPopup.hide();
}
+ /**
+ * Sets the icon URI of the selected item. The icon is shown on the left
+ * side of the item caption text. Set the URI to null to remove the icon.
+ *
+ * @param iconUri
+ * The URI of the icon
+ */
private void setSelectedItemIcon(String iconUri) {
if (iconUri == null || iconUri == "") {
panel.remove(selectedItemIcon);
@@ -918,6 +1108,10 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Positions the icon vertically in the middle. Should be called after the
+ * icon has loaded
+ */
private void updateSelectedIconPosition() {
// Position icon vertically to middle
int availableHeight = getOffsetHeight();
@@ -927,6 +1121,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
marginTop + "px");
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
+ * .event.dom.client.KeyDownEvent)
+ */
public void onKeyDown(KeyDownEvent event) {
if (enabled && !readonly) {
if (suggestionPopup.isAttached()) {
@@ -937,6 +1138,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Triggered when a key is pressed in the text box
+ *
+ * @param event
+ * The KeyDownEvent
+ */
private void inputFieldKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_DOWN:
@@ -959,6 +1166,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
+ /**
+ * Triggered when a key was pressed in the suggestion popup
+ *
+ * @param event
+ * The KeyDownEvent of the key
+ */
private void popupKeyDown(KeyDownEvent event) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_DOWN:
@@ -1001,6 +1214,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
+ /**
+ * Triggered when a key was depressed
+ *
+ * @param event
+ * The KeyUpEvent of the key depressed
+ */
public void onKeyUp(KeyUpEvent event) {
if (enabled && !readonly) {
switch (event.getNativeKeyCode()) {
@@ -1025,6 +1244,9 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Resets the Select to its initial state
+ */
private void reset() {
if (currentSuggestion != null) {
String text = currentSuggestion.getReplacementString();
@@ -1060,8 +1282,8 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
- /*
- * Calculate minumum width for FilterSelect textarea
+ /**
+ * Calculate minimum width for FilterSelect textarea
*/
private native int minWidth(String captions)
/*-{
@@ -1085,6 +1307,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
return w;
}-*/;
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
+ * .dom.client.FocusEvent)
+ */
public void onFocus(FocusEvent event) {
focused = true;
if (prompting && !readonly) {
@@ -1097,6 +1326,13 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
+ * .dom.client.BlurEvent)
+ */
public void onBlur(BlurEvent event) {
focused = false;
if (!readonly) {
@@ -1120,6 +1356,11 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.Focusable#focus()
+ */
public void focus() {
focused = true;
if (prompting && !readonly) {
@@ -1128,6 +1369,11 @@ public class VFilterSelect extends Composite implements Paintable, Field,
tb.setFocus(true);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.UIObject#setWidth(java.lang.String)
+ */
@Override
public void setWidth(String width) {
if (width == null || width.equals("")) {
@@ -1143,12 +1389,21 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.UIObject#setHeight(java.lang.String)
+ */
@Override
public void setHeight(String height) {
super.setHeight(height);
Util.setHeightExcludingPaddingAndBorder(tb, height, 3);
}
+ /**
+ * Calculates the width of the select if the select has undefined width.
+ * Should be called when the width changes or when the icon changes.
+ */
private void updateRootWidth() {
if (width == null) {
/*
@@ -1190,6 +1445,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
}
}
+ /**
+ * Get the width of the select in pixels where the text area and icon has
+ * been included.
+ *
+ * @return The width in pixels
+ */
private int getMainWidth() {
int componentWidth;
if (BrowserInfo.get().isIE6()) {
@@ -1203,6 +1464,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
return componentWidth;
}
+ /**
+ * Sets the text box width in pixels.
+ *
+ * @param componentWidth
+ * The width of the text box in pixels
+ */
private void setTextboxWidth(int componentWidth) {
int padding = getTextboxPadding();
int popupOpenerWidth = Util.getRequiredWidth(popupOpener);
@@ -1216,6 +1483,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
tb.setWidth(textboxWidth + "px");
}
+ /**
+ * Gets the horizontal padding of the text box in pixels. The measurement
+ * includes the border width.
+ *
+ * @return The padding in pixels
+ */
private int getTextboxPadding() {
if (textboxPadding < 0) {
textboxPadding = Util.measureHorizontalPaddingAndBorder(tb
@@ -1224,6 +1497,12 @@ public class VFilterSelect extends Composite implements Paintable, Field,
return textboxPadding;
}
+ /**
+ * Gets the horizontal padding of the select. The measurement includes the
+ * border width.
+ *
+ * @return The padding in pixels
+ */
private int getComponentPadding() {
if (componentPadding < 0) {
componentPadding = Util.measureHorizontalPaddingAndBorder(
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
index 541b6e92d0..8d5c21c512 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VPopupCalendar.java
@@ -67,16 +67,17 @@ public class VPopupCalendar extends VTextualDate implements Paintable, Field,
calendarToggle.setTabIndex(uidl.getIntAttribute("tabindex"));
}
- if (lastReadOnlyState != readonly) {
- updateWidth();
- }
-
- calendarToggle.setEnabled(true);
if (readonly) {
calendarToggle.addStyleName(CLASSNAME + "-button-readonly");
} else {
calendarToggle.removeStyleName(CLASSNAME + "-button-readonly");
}
+
+ if (lastReadOnlyState != readonly) {
+ updateWidth();
+ }
+
+ calendarToggle.setEnabled(true);
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index 249fe75938..6c90bde5f0 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -628,41 +628,81 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
HttpServletResponse response, String caption, String message,
String details, String url) throws IOException {
- if (!isUIDLRequest(request)) {
- throw new RuntimeException(
- "criticalNotification can only be used in UIDL requests");
- }
+ if (isUIDLRequest(request)) {
- if (caption != null) {
- caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
- }
- if (details != null) {
- if (message == null) {
- message = details;
- } else {
- message += "<br/><br/>" + details;
+ if (caption != null) {
+ caption = "\"" + JsonPaintTarget.escapeJSON(caption) + "\"";
+ }
+ if (details != null) {
+ if (message == null) {
+ message = details;
+ } else {
+ message += "<br/><br/>" + details;
+ }
}
- }
- if (message != null) {
- message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
- }
- if (url != null) {
- url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
+ if (message != null) {
+ message = "\"" + JsonPaintTarget.escapeJSON(message) + "\"";
+ }
+ if (url != null) {
+ url = "\"" + JsonPaintTarget.escapeJSON(url) + "\"";
+ }
+
+ String output = "for(;;);[{\"changes\":[], \"meta\" : {"
+ + "\"appError\": {" + "\"caption\":" + caption + ","
+ + "\"message\" : " + message + "," + "\"url\" : " + url
+ + "}}, \"resources\": {}, \"locales\":[]}]";
+ writeResponse(response, "application/json; charset=UTF-8", output);
+ } else {
+ // Create an HTML reponse with the error
+ String output = "";
+
+ if (url != null) {
+ output += "<a href=\"" + url + "\">";
+ }
+ if (caption != null) {
+ output += "<b>" + caption + "</b><br/>";
+ }
+ if (message != null) {
+ output += message;
+ output += "<br/><br/>";
+ }
+
+ if (details != null) {
+ output += details;
+ output += "<br/><br/>";
+ }
+ if (url != null) {
+ output += "</a>";
+ }
+ writeResponse(response, "text/html; charset=UTF-8", output);
+
}
- // Set the response type
- response.setContentType("application/json; charset=UTF-8");
+ }
+
+ /**
+ * Writes the response in {@code output} using the contentType given in
+ * {@code contentType} to the provided {@link HttpServletResponse}
+ *
+ * @param response
+ * @param contentType
+ * @param output
+ * Output to write (UTF-8 encoded)
+ * @throws IOException
+ */
+ private void writeResponse(HttpServletResponse response,
+ String contentType, String output) throws IOException {
+ response.setContentType(contentType);
final ServletOutputStream out = response.getOutputStream();
+ // Set the response type
final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(out, "UTF-8")));
- outWriter.print("for(;;);[{\"changes\":[], \"meta\" : {"
- + "\"appError\": {" + "\"caption\":" + caption + ","
- + "\"message\" : " + message + "," + "\"url\" : " + url
- + "}}, \"resources\": {}, \"locales\":[]}]");
+ outWriter.print(output);
outWriter.flush();
outWriter.close();
out.flush();
+
}
/**
@@ -1755,7 +1795,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
page.write(VERSION);
page.write("\",applicationVersion:\"");
page.write(application.getVersion());
- page.write("\"},");
+ page.write("\"}");
if (systemMessages != null) {
// Write the CommunicationError -message to client
String caption = systemMessages.getCommunicationErrorCaption();
@@ -1771,7 +1811,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
url = "\"" + url + "\"";
}
- page.write("\"comErrMsg\": {" + "\"caption\":" + caption + ","
+ page.write(",\"comErrMsg\": {" + "\"caption\":" + caption + ","
+ "\"message\" : " + message + "," + "\"url\" : " + url
+ "}");
}
diff --git a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
index 0b84990508..5709bc6a8d 100644
--- a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java
@@ -258,13 +258,15 @@ public class GAEApplicationServlet extends ApplicationServlet {
log.severe("DeadlineExceeded for " + session.getId());
sendDeadlineExceededNotification(request, response);
} catch (NotSerializableException e) {
+ log.severe("NotSerializableException: " + getStackTraceAsString(e));
+
// TODO this notification is usually not shown - should we redirect
// in some other way - can we?
sendNotSerializableNotification(request, response);
- log.severe("NotSerializableException: " + getStackTraceAsString(e));
} catch (Exception e) {
- sendCriticalErrorNotification(request, response);
log.severe(e + ": " + getStackTraceAsString(e));
+
+ sendCriticalErrorNotification(request, response);
} finally {
// "Next, please!"
if (locked) {
diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java
index 1e31eb9b65..18a602280b 100644
--- a/src/com/vaadin/ui/GridLayout.java
+++ b/src/com/vaadin/ui/GridLayout.java
@@ -1185,7 +1185,8 @@ public class GridLayout extends AbstractLayout implements
* row.
* <p>
* If the last row is removed then all remaining components will be removed
- * and the grid will be reduced to one row and one column.
+ * and the grid will be reduced to one row. The cursor will be moved to the
+ * upper left cell of the grid.
* </p>
*
* @param row
@@ -1217,9 +1218,10 @@ public class GridLayout extends AbstractLayout implements
if (rows == 1) {
/*
* Removing the last row means that the dimensions of the Grid
- * layout will be truncated to 1x1 and all components removed.
+ * layout will be truncated to 1 empty row and the cursor is moved
+ * to the first cell
*/
- setColumns(1);
+ cursorX = 0;
cursorY = 0;
} else {
setRows(rows - 1);
diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java
index 77f2653f0a..a69e89ee17 100644
--- a/src/com/vaadin/ui/TabSheet.java
+++ b/src/com/vaadin/ui/TabSheet.java
@@ -101,7 +101,8 @@ public class TabSheet extends AbstractComponentContainer {
if (components.isEmpty()) {
selected = null;
} else {
- selected = components.getFirst();
+ // select the first enabled and visible tab, if any
+ updateSelection();
fireSelectedTabChange();
}
}
@@ -217,30 +218,6 @@ public class TabSheet extends AbstractComponentContainer {
Tab tab = tabs.get(component);
- /*
- * If we have no selection, if the current selection is invisible or
- * if the current selection is disabled (but the whole component is
- * not) we select this tab instead
- */
- Tab selectedTabInfo = null;
- if (selected != null) {
- selectedTabInfo = tabs.get(selected);
- }
- if (selected == null || selectedTabInfo == null
- || !selectedTabInfo.isVisible()
- || !selectedTabInfo.isEnabled()) {
-
- // The current selection is not valid so we need to change it
- if (tab.isEnabled() && tab.isVisible()) {
- selected = component;
- } else {
- /*
- * The current selection is not valid but this tab cannot be
- * selected either.
- */
- selected = null;
- }
- }
target.startTag("tab");
if (!tab.isEnabled() && tab.isVisible()) {
target.addAttribute("disabled", true);
@@ -414,12 +391,58 @@ public class TabSheet extends AbstractComponentContainer {
public void setSelectedTab(Component c) {
if (c != null && components.contains(c) && !c.equals(selected)) {
selected = c;
+ updateSelection();
fireSelectedTabChange();
requestRepaint();
}
}
/**
+ * Checks if the current selection is valid, and updates the selection if
+ * the previously selected component is not visible and enabled.
+ *
+ * This method does not fire tab change events, but the caller should do so
+ * if appropriate.
+ *
+ * @return true if selection was changed, false otherwise
+ */
+ private boolean updateSelection() {
+ Component originalSelection = selected;
+ for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) {
+ final Component component = i.next();
+
+ Tab tab = tabs.get(component);
+
+ /*
+ * If we have no selection, if the current selection is invisible or
+ * if the current selection is disabled (but the whole component is
+ * not) we select this tab instead
+ */
+ Tab selectedTabInfo = null;
+ if (selected != null) {
+ selectedTabInfo = tabs.get(selected);
+ }
+ if (selected == null || selectedTabInfo == null
+ || !selectedTabInfo.isVisible()
+ || !selectedTabInfo.isEnabled()) {
+
+ // The current selection is not valid so we need to change
+ // it
+ if (tab.isEnabled() && tab.isVisible()) {
+ selected = component;
+ } else {
+ /*
+ * The current selection is not valid but this tab cannot be
+ * selected either.
+ */
+ selected = null;
+ }
+ }
+ }
+ return originalSelection != selected;
+ }
+
+ /**
* Gets the selected tab.
*
* @return the selected tab.
@@ -795,6 +818,9 @@ public class TabSheet extends AbstractComponentContainer {
public void setEnabled(boolean enabled) {
this.enabled = enabled;
+ if (updateSelection()) {
+ fireSelectedTabChange();
+ }
requestRepaint();
}
@@ -804,6 +830,9 @@ public class TabSheet extends AbstractComponentContainer {
public void setVisible(boolean visible) {
this.visible = visible;
+ if (updateSelection()) {
+ fireSelectedTabChange();
+ }
requestRepaint();
}