Fix and test case for #4222 svn changeset:11485/svn branch:6.3tags/6.7.0.beta1
@@ -36,14 +36,20 @@ import com.vaadin.terminal.gwt.client.ui.VScrollTable; | |||
/** | |||
* <p> | |||
* <code>TableComponent</code> is used for representing data or components in | |||
* pageable and selectable table. | |||
* <code>Table</code> is used for representing data or components in a pageable | |||
* and selectable table. | |||
* </p> | |||
* | |||
* <p> | |||
* Note! Since version 5, components in Table will not have their caption nor | |||
* icon rendered. In order to workaround this limitation, wrap your component in | |||
* a Layout. | |||
* Scalability of the Table is largely dictated by the container. A table does | |||
* not have a limit for the number of items and is just as fast with hundreds of | |||
* thousands of items as with just a few. The current GWT implementation with | |||
* scrolling however limits the number of rows to around 500000, depending on | |||
* the browser and the pixel height of rows. | |||
* </p> | |||
* | |||
* <p> | |||
* Components in a Table will not have their caption nor icon rendered. | |||
* </p> | |||
* | |||
* @author IT Mill Ltd. | |||
@@ -502,6 +508,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
} | |||
// Assures the visual refresh | |||
// FIXME: Is this really needed? Header captions should not affect | |||
// content so requestRepaint() should be sufficient. | |||
resetPageBuffer(); | |||
refreshRenderedCells(); | |||
} | |||
@@ -971,6 +979,8 @@ public class Table extends AbstractSelect implements Action.Container, | |||
columnHeaders.put(propertyId, header); | |||
// Assures the visual refresh | |||
// FIXME: Is this really needed? Header captions should not affect | |||
// content so requestRepaint() should be sufficient. | |||
refreshRenderedCells(); | |||
} | |||
@@ -1053,28 +1053,63 @@ public class Window extends Panel implements URIHandler, ParameterHandler { | |||
} | |||
} | |||
/** | |||
* An interface used for listening to Window close events. Add the | |||
* CloseListener to a browser level window or a sub window and | |||
* {@link CloseListener#windowClose(CloseEvent)} will be called whenever the | |||
* user closes the window. | |||
* | |||
* <p> | |||
* Note that removing windows using {@link #removeWindow(Window)} will not | |||
* fire the CloseListener. | |||
* </p> | |||
*/ | |||
public interface CloseListener extends Serializable { | |||
/** | |||
* Called when the user closes a window. Use | |||
* {@link CloseEvent#getWindow()} to get a reference to the | |||
* {@link Window} that was closed. | |||
* | |||
* @param e | |||
* Event containing | |||
*/ | |||
public void windowClose(CloseEvent e); | |||
} | |||
/** | |||
* Adds the listener. | |||
* Adds a CloseListener to the window. | |||
* | |||
* For a sub window the CloseListener is fired when the user closes it | |||
* (clicks on the close button). | |||
* | |||
* For a browser level window the CloseListener is fired when the browser | |||
* level window is closed. Note that closing a browser level window does not | |||
* mean it will be destroyed. | |||
* | |||
* <p> | |||
* Note that removing windows using {@link #removeWindow(Window)} will not | |||
* fire the CloseListener. | |||
* </p> | |||
* | |||
* @param listener | |||
* the listener to add. | |||
* the CloseListener to add. | |||
*/ | |||
public void addListener(CloseListener listener) { | |||
addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); | |||
} | |||
/** | |||
* Removes the listener. | |||
* Removes the CloseListener from the window. | |||
* | |||
* <p> | |||
* For more information on CloseListeners see {@link CloseListener}. | |||
* </p> | |||
* | |||
* @param listener | |||
* the listener to remove. | |||
* the CloseListener to remove. | |||
*/ | |||
public void removeListener(CloseListener listener) { | |||
addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); | |||
removeListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); | |||
} | |||
protected void fireClose() { |
@@ -0,0 +1,90 @@ | |||
package com.vaadin.tests.server.components; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import junit.framework.TestCase; | |||
import org.easymock.EasyMock; | |||
import com.vaadin.ui.Window; | |||
import com.vaadin.ui.Window.CloseEvent; | |||
import com.vaadin.ui.Window.CloseListener; | |||
import com.vaadin.ui.Window.ResizeEvent; | |||
import com.vaadin.ui.Window.ResizeListener; | |||
public class TestWindow extends TestCase { | |||
private Window window; | |||
@Override | |||
protected void setUp() throws Exception { | |||
window = new Window(); | |||
} | |||
public void testCloseListener() { | |||
CloseListener cl = EasyMock.createMock(Window.CloseListener.class); | |||
// Expectations | |||
cl.windowClose(EasyMock.isA(CloseEvent.class)); | |||
// Start actual test | |||
EasyMock.replay(cl); | |||
// Add listener and send a close event -> should end up in listener once | |||
window.addListener(cl); | |||
sendClose(window); | |||
// Ensure listener was called once | |||
EasyMock.verify(cl); | |||
// Remove the listener and send close event -> should not end up in | |||
// listener | |||
window.removeListener(cl); | |||
sendClose(window); | |||
// Ensure listener still has been called only once | |||
EasyMock.verify(cl); | |||
} | |||
public void testResizeListener() { | |||
ResizeListener rl = EasyMock.createMock(Window.ResizeListener.class); | |||
// Expectations | |||
rl.windowResized(EasyMock.isA(ResizeEvent.class)); | |||
// Start actual test | |||
EasyMock.replay(rl); | |||
// Add listener and send a resize event -> should end up in listener | |||
// once | |||
window.addListener(rl); | |||
sendResize(window); | |||
// Ensure listener was called once | |||
EasyMock.verify(rl); | |||
// Remove the listener and send close event -> should not end up in | |||
// listener | |||
window.removeListener(rl); | |||
sendResize(window); | |||
// Ensure listener still has been called only once | |||
EasyMock.verify(rl); | |||
} | |||
private void sendResize(Window window2) { | |||
Map<String, Object> variables = new HashMap<String, Object>(); | |||
variables.put("height", 1234); | |||
window.changeVariables(window, variables); | |||
} | |||
private static void sendClose(Window window) { | |||
Map<String, Object> variables = new HashMap<String, Object>(); | |||
variables.put("close", true); | |||
window.changeVariables(window, variables); | |||
} | |||
} |