Change-Id: I2d12b8876bee47030383cf4845efd49eaeee72eetags/7.0.0.beta9
@@ -15,86 +15,56 @@ | |||
*/ | |||
package com.vaadin.client.ui.popupview; | |||
import com.vaadin.client.ApplicationConnection; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import com.google.gwt.event.shared.HandlerRegistration; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.ConnectorHierarchyChangeEvent; | |||
import com.vaadin.client.Paintable; | |||
import com.vaadin.client.UIDL; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.VCaptionWrapper; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.AbstractComponentContainerConnector; | |||
import com.vaadin.client.ui.PostLayoutListener; | |||
import com.vaadin.shared.ui.ComponentStateUtil; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.shared.ui.popupview.PopupViewServerRpc; | |||
import com.vaadin.shared.ui.popupview.PopupViewState; | |||
import com.vaadin.ui.PopupView; | |||
@Connect(PopupView.class) | |||
public class PopupViewConnector extends AbstractComponentContainerConnector | |||
implements Paintable, PostLayoutListener { | |||
implements PostLayoutListener, VisibilityChangeHandler { | |||
private boolean centerAfterLayout = false; | |||
private final List<HandlerRegistration> handlerRegistration = new ArrayList<HandlerRegistration>(); | |||
@Override | |||
protected void init() { | |||
super.init(); | |||
handlerRegistration.add(getWidget().addVisibilityChangeHandler( | |||
this)); | |||
} | |||
@Override | |||
public boolean delegateCaptionHandling() { | |||
return false; | |||
} | |||
/** | |||
* | |||
* | |||
* @see com.vaadin.client.ComponentConnector#updateFromUIDL(com.vaadin.client.UIDL, | |||
* com.vaadin.client.ApplicationConnection) | |||
*/ | |||
@Override | |||
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { | |||
if (!isRealUpdate(uidl)) { | |||
return; | |||
} | |||
// These are for future server connections | |||
getWidget().client = client; | |||
getWidget().uidlId = uidl.getId(); | |||
getWidget().hostPopupVisible = uidl | |||
.getBooleanVariable("popupVisibility"); | |||
public void onStateChanged(StateChangeEvent stateChangeEvent) { | |||
super.onStateChanged(stateChangeEvent); | |||
getWidget().setHTML(uidl.getStringAttribute("html")); | |||
if (uidl.hasAttribute("hideOnMouseOut")) { | |||
getWidget().popup.setHideOnMouseOut(uidl | |||
.getBooleanAttribute("hideOnMouseOut")); | |||
} | |||
// Render the popup if visible and show it. | |||
if (getWidget().hostPopupVisible) { | |||
UIDL popupUIDL = uidl.getChildUIDL(0); | |||
// showPopupOnTop(popup, hostReference); | |||
getWidget().preparePopup(getWidget().popup); | |||
getWidget().popup.updateFromUIDL(popupUIDL, client); | |||
if (ComponentStateUtil.hasStyles(getState())) { | |||
final StringBuffer styleBuf = new StringBuffer(); | |||
final String primaryName = getWidget().popup | |||
.getStylePrimaryName(); | |||
styleBuf.append(primaryName); | |||
for (String style : getState().styles) { | |||
styleBuf.append(" "); | |||
styleBuf.append(primaryName); | |||
styleBuf.append("-"); | |||
styleBuf.append(style); | |||
} | |||
getWidget().popup.setStyleName(styleBuf.toString()); | |||
} else { | |||
getWidget().popup.setStyleName(getWidget().popup | |||
.getStylePrimaryName()); | |||
} | |||
getWidget().showPopup(getWidget().popup); | |||
centerAfterLayout = true; | |||
getWidget().setHTML(getState().html); | |||
getWidget().popup.setHideOnMouseOut(getState().hideOnMouseOut); | |||
} | |||
// The popup shouldn't be visible, try to hide it. | |||
} else { | |||
getWidget().popup.hide(); | |||
} | |||
}// updateFromUIDL | |||
@Override | |||
public PopupViewState getState() { | |||
return (PopupViewState) super.getState(); | |||
} | |||
@Override | |||
public void updateCaption(ComponentConnector component) { | |||
@@ -131,7 +101,41 @@ public class PopupViewConnector extends AbstractComponentContainerConnector | |||
@Override | |||
public void onConnectorHierarchyChange( | |||
ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) { | |||
// TODO Move code from updateFromUIDL to this method | |||
// Render the popup if visible and show it. | |||
if (!getChildren().isEmpty()) { | |||
getWidget().preparePopup(getWidget().popup); | |||
getWidget().popup | |||
.setPopupConnector((ComponentConnector) getChildren() | |||
.get(0)); | |||
if (ComponentStateUtil.hasStyles(getState())) { | |||
final StringBuffer styleBuf = new StringBuffer(); | |||
final String primaryName = getWidget().popup | |||
.getStylePrimaryName(); | |||
styleBuf.append(primaryName); | |||
for (String style : getState().styles) { | |||
styleBuf.append(" "); | |||
styleBuf.append(primaryName); | |||
styleBuf.append("-"); | |||
styleBuf.append(style); | |||
} | |||
getWidget().popup.setStyleName(styleBuf.toString()); | |||
} else { | |||
getWidget().popup.setStyleName(getWidget().popup | |||
.getStylePrimaryName()); | |||
} | |||
getWidget().showPopup(getWidget().popup); | |||
centerAfterLayout = true; | |||
// The popup shouldn't be visible, try to hide it. | |||
} else { | |||
getWidget().popup.hide(); | |||
} | |||
} | |||
@Override | |||
public void onVisibilityChange(VisibilityChangeEvent event) { | |||
getRpcProxy(PopupViewServerRpc.class).setPopupVisibility( | |||
event.isVisible()); | |||
} | |||
} | |||
} |
@@ -26,6 +26,7 @@ import com.google.gwt.event.dom.client.KeyDownEvent; | |||
import com.google.gwt.event.dom.client.KeyDownHandler; | |||
import com.google.gwt.event.logical.shared.CloseEvent; | |||
import com.google.gwt.event.logical.shared.CloseHandler; | |||
import com.google.gwt.event.shared.HandlerRegistration; | |||
import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Element; | |||
import com.google.gwt.user.client.Event; | |||
@@ -36,9 +37,7 @@ import com.google.gwt.user.client.ui.Label; | |||
import com.google.gwt.user.client.ui.PopupPanel; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.UIDL; | |||
import com.vaadin.client.VCaptionWrapper; | |||
import com.vaadin.client.VConsole; | |||
import com.vaadin.client.ui.ShortcutActionHandler; | |||
@@ -50,10 +49,6 @@ public class VPopupView extends HTML { | |||
public static final String CLASSNAME = "v-popupview"; | |||
/** For server-client communication */ | |||
String uidlId; | |||
ApplicationConnection client; | |||
/** This variable helps to communicate popup visibility to the server */ | |||
boolean hostPopupVisible; | |||
@@ -78,7 +73,7 @@ public class VPopupView extends HTML { | |||
addClickHandler(new ClickHandler() { | |||
@Override | |||
public void onClick(ClickEvent event) { | |||
updateState(true); | |||
fireEvent(new VisibilityChangeEvent(true)); | |||
} | |||
}); | |||
@@ -86,25 +81,13 @@ public class VPopupView extends HTML { | |||
popup.addCloseHandler(new CloseHandler<PopupPanel>() { | |||
@Override | |||
public void onClose(CloseEvent<PopupPanel> event) { | |||
updateState(false); | |||
fireEvent(new VisibilityChangeEvent(false)); | |||
} | |||
}); | |||
popup.setAnimationEnabled(true); | |||
} | |||
/** | |||
* Update popup visibility to server | |||
* | |||
* @param visibility | |||
*/ | |||
private void updateState(boolean visible) { | |||
// If we know the server connection | |||
// then update the current situation | |||
if (uidlId != null && client != null && isAttached()) { | |||
client.updateVariable(uidlId, "popupVisibility", visible, true); | |||
} | |||
} | |||
void preparePopup(final CustomPopup popup) { | |||
popup.setVisible(false); | |||
@@ -191,7 +174,7 @@ public class VPopupView extends HTML { | |||
*/ | |||
protected class CustomPopup extends VOverlay { | |||
private ComponentConnector popupComponentPaintable = null; | |||
private ComponentConnector popupComponentConnector = null; | |||
Widget popupComponentWidget = null; | |||
VCaptionWrapper captionWrapper = null; | |||
@@ -327,23 +310,20 @@ public class VPopupView extends HTML { | |||
@Override | |||
public boolean remove(Widget w) { | |||
popupComponentPaintable = null; | |||
popupComponentConnector = null; | |||
popupComponentWidget = null; | |||
captionWrapper = null; | |||
return super.remove(w); | |||
} | |||
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { | |||
ComponentConnector newPopupComponent = client.getPaintable(uidl | |||
.getChildUIDL(0)); | |||
public void setPopupConnector(ComponentConnector newPopupComponent) { | |||
if (newPopupComponent != popupComponentPaintable) { | |||
if (newPopupComponent != popupComponentConnector) { | |||
Widget newWidget = newPopupComponent.getWidget(); | |||
setWidget(newWidget); | |||
popupComponentWidget = newWidget; | |||
popupComponentPaintable = newPopupComponent; | |||
popupComponentConnector = newPopupComponent; | |||
} | |||
} | |||
@@ -384,4 +364,10 @@ public class VPopupView extends HTML { | |||
}// class CustomPopup | |||
public HandlerRegistration addVisibilityChangeHandler( | |||
final VisibilityChangeHandler visibilityChangeHandler) { | |||
return addHandler(visibilityChangeHandler, | |||
VisibilityChangeEvent.getType()); | |||
} | |||
}// class VPopupView |
@@ -0,0 +1,36 @@ | |||
package com.vaadin.client.ui.popupview; | |||
import com.google.gwt.event.shared.GwtEvent; | |||
public class VisibilityChangeEvent extends | |||
GwtEvent<VisibilityChangeHandler> { | |||
private static Type<VisibilityChangeHandler> TYPE; | |||
private boolean visible; | |||
public VisibilityChangeEvent(final boolean visible) { | |||
this.visible = visible; | |||
} | |||
public boolean isVisible() { | |||
return visible; | |||
} | |||
@Override | |||
public Type<VisibilityChangeHandler> getAssociatedType() { | |||
return getType(); | |||
} | |||
public static Type<VisibilityChangeHandler> getType() { | |||
if (TYPE == null) { | |||
TYPE = new Type<VisibilityChangeHandler>(); | |||
} | |||
return TYPE; | |||
} | |||
@Override | |||
protected void dispatch(final VisibilityChangeHandler handler) { | |||
handler.onVisibilityChange(this); | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
package com.vaadin.client.ui.popupview; | |||
import com.google.gwt.event.shared.EventHandler; | |||
public interface VisibilityChangeHandler extends EventHandler { | |||
void onVisibilityChange(VisibilityChangeEvent event); | |||
} |
@@ -18,11 +18,9 @@ package com.vaadin.ui; | |||
import java.io.Serializable; | |||
import java.lang.reflect.Method; | |||
import java.util.Iterator; | |||
import java.util.Map; | |||
import com.vaadin.server.LegacyPaint; | |||
import com.vaadin.server.PaintException; | |||
import com.vaadin.server.PaintTarget; | |||
import com.vaadin.shared.ui.popupview.PopupViewServerRpc; | |||
import com.vaadin.shared.ui.popupview.PopupViewState; | |||
/** | |||
* | |||
@@ -34,11 +32,9 @@ import com.vaadin.server.PaintTarget; | |||
* @author Vaadin Ltd. | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class PopupView extends AbstractComponentContainer implements | |||
LegacyComponent { | |||
public class PopupView extends AbstractComponentContainer { | |||
private Content content; | |||
private boolean hideOnMouseOut; | |||
private Component visibleComponent; | |||
private static final Method POPUP_VISIBILITY_METHOD; | |||
@@ -54,6 +50,14 @@ public class PopupView extends AbstractComponentContainer implements | |||
} | |||
} | |||
private final PopupViewServerRpc rpc = new PopupViewServerRpc() { | |||
@Override | |||
public void setPopupVisibility(boolean visible) { | |||
setPopupVisible(visible); | |||
} | |||
}; | |||
/** | |||
* Iterator for the visible components (zero or one components), used by | |||
* {@link PopupView#getComponentIterator()}. | |||
@@ -126,7 +130,8 @@ public class PopupView extends AbstractComponentContainer implements | |||
*/ | |||
public PopupView(PopupView.Content content) { | |||
super(); | |||
hideOnMouseOut = true; | |||
registerRpc(rpc); | |||
setHideOnMouseOut(true); | |||
setContent(content); | |||
} | |||
@@ -182,6 +187,16 @@ public class PopupView extends AbstractComponentContainer implements | |||
} | |||
} | |||
@Override | |||
public void beforeClientResponse(boolean initial) { | |||
super.beforeClientResponse(initial); | |||
String html = content.getMinimizedValueAsHTML(); | |||
if (html == null) { | |||
html = ""; | |||
} | |||
getState().html = html; | |||
} | |||
/** | |||
* Return whether the popup is visible. | |||
* | |||
@@ -198,7 +213,7 @@ public class PopupView extends AbstractComponentContainer implements | |||
* @return true if the popup is hidden on mouse out, false otherwise | |||
*/ | |||
public boolean isHideOnMouseOut() { | |||
return hideOnMouseOut; | |||
return getState().hideOnMouseOut; | |||
} | |||
/** | |||
@@ -210,7 +225,7 @@ public class PopupView extends AbstractComponentContainer implements | |||
* | |||
*/ | |||
public void setHideOnMouseOut(boolean hideOnMouseOut) { | |||
this.hideOnMouseOut = hideOnMouseOut; | |||
getState().hideOnMouseOut = hideOnMouseOut; | |||
} | |||
/* | |||
@@ -301,46 +316,9 @@ public class PopupView extends AbstractComponentContainer implements | |||
} | |||
/* | |||
* Methods for server-client communications. | |||
*/ | |||
/** | |||
* Paint (serialize) the component for the client. | |||
* | |||
* @see com.vaadin.ui.AbstractComponent#paintContent(com.vaadin.server.PaintTarget) | |||
*/ | |||
@Override | |||
public void paintContent(PaintTarget target) throws PaintException { | |||
String html = content.getMinimizedValueAsHTML(); | |||
if (html == null) { | |||
html = ""; | |||
} | |||
target.addAttribute("html", html); | |||
target.addAttribute("hideOnMouseOut", hideOnMouseOut); | |||
// Only paint component to client if we know that the popup is showing | |||
if (isPopupVisible()) { | |||
target.startTag("popupComponent"); | |||
LegacyPaint.paint(visibleComponent, target); | |||
target.endTag("popupComponent"); | |||
} | |||
target.addVariable(this, "popupVisibility", isPopupVisible()); | |||
} | |||
/** | |||
* Deserialize changes received from client. | |||
* | |||
* @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, | |||
* java.util.Map) | |||
*/ | |||
@Override | |||
public void changeVariables(Object source, Map<String, Object> variables) { | |||
if (variables.containsKey("popupVisibility")) { | |||
setPopupVisible(((Boolean) variables.get("popupVisibility")) | |||
.booleanValue()); | |||
} | |||
protected PopupViewState getState() { | |||
return (PopupViewState) super.getState(); | |||
} | |||
/** |
@@ -0,0 +1,10 @@ | |||
package com.vaadin.shared.ui.popupview; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
public interface PopupViewServerRpc extends ServerRpc { | |||
public void setPopupVisibility(boolean visible); | |||
} |
@@ -0,0 +1,10 @@ | |||
package com.vaadin.shared.ui.popupview; | |||
import com.vaadin.shared.ComponentState; | |||
public class PopupViewState extends ComponentState { | |||
public String html; | |||
public boolean hideOnMouseOut; | |||
} |
@@ -1,10 +1,10 @@ | |||
package com.vaadin.tests.components.combobox; | |||
import java.util.Map; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.ComboBox; | |||
import com.vaadin.ui.PopupView; | |||
import com.vaadin.ui.PopupView.PopupVisibilityEvent; | |||
import com.vaadin.ui.PopupView.PopupVisibilityListener; | |||
public class ComboBoxInPopupView extends TestBase { | |||
@@ -28,15 +28,14 @@ public class ComboBoxInPopupView extends TestBase { | |||
final ComboBox cb2 = new ComboBox(); | |||
cb2.setWidth("260px"); | |||
PopupView pv2 = new PopupView("<u>2. focused (click)</u>", cb2) { | |||
PopupView pv2 = new PopupView("<u>2. focused (click)</u>", cb2); | |||
pv2.addListener(new PopupVisibilityListener() { | |||
@Override | |||
public void changeVariables(Object source, | |||
Map<String, Object> variables) { | |||
super.changeVariables(source, variables); | |||
public void popupVisibilityChange(PopupVisibilityEvent event) { | |||
cb2.focus(); | |||
} | |||
}; | |||
}); | |||
getLayout().addComponent(pv2); | |||
} |