Browse Source

Fixed regression with changing widths when stylenames have changed (#13444, #8801):

Changing the name of a style should not cause the width of the textbox
to change. If there is a width set for the wrapper, the width for the
wrapper should not change if the styles changes.

To reconcile these two demands, we have removed the width for the
wrapper and only manipulate the width of the textbox itself. This
solves both issues neatly.

Change-Id: Idb2dbc5d2ca6406cafb44df93110e079a1dff473
tags/7.3.0.beta1
Markus Koivisto 10 years ago
parent
commit
297c97a7a9

+ 55
- 54
client/src/com/vaadin/client/ui/VFilterSelect.java View File



/** /**
* Client side implementation of the Select component. * Client side implementation of the Select component.
*
*
* TODO needs major refactoring (to be extensible etc) * TODO needs major refactoring (to be extensible etc)
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")


/** /**
* Constructor * Constructor
*
*
* @param uidl * @param uidl
* The UIDL recieved from the server * The UIDL recieved from the server
*/ */


/** /**
* Get the option key which represents the item on the server side. * Get the option key which represents the item on the server side.
*
*
* @return The key of the item * @return The key of the item
*/ */
public String getOptionKey() { public String getOptionKey() {


/** /**
* Get the URI of the icon. Used when constructing the displayed option. * Get the URI of the icon. Used when constructing the displayed option.
*
*
* @return * @return
*/ */
public String getIconUri() { public String getIconUri() {


/** /**
* Shows the popup where the user can see the filtered options * Shows the popup where the user can see the filtered options
*
*
* @param currentSuggestions * @param currentSuggestions
* The filtered suggestions * The filtered suggestions
* @param currentPage * @param currentPage


/** /**
* Should the next page button be visible to the user? * Should the next page button be visible to the user?
*
*
* @param active * @param active
*/ */
private void setNextButtonActive(boolean active) { private void setNextButtonActive(boolean active) {


/** /**
* Should the previous page button be visible to the user * Should the previous page button be visible to the user
*
*
* @param active * @param active
*/ */
private void setPrevButtonActive(boolean active) { private void setPrevButtonActive(boolean active) {
* because otherwise the waiting flag will be reset in * because otherwise the waiting flag will be reset in
* the first response and the second response will be * the first response and the second response will be
* ignored, causing an empty popup... * ignored, causing an empty popup...
*
*
* As long as the scrolling delay is suitable * As long as the scrolling delay is suitable
* double/triple clicks will work by scrolling two or * double/triple clicks will work by scrolling two or
* three pages at a time and this should not be a * three pages at a time and this should not be a


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
* .user.client.Event) * .user.client.Event)
* amount of items are visible at a time and a scrollbar or buttons are * 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 * visible to change page. If paging is turned of then all options are
* rendered into the popup menu. * rendered into the popup menu.
*
*
* @param paging * @param paging
* Should the paging be turned on? * Should the paging be turned on?
*/ */


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition * com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition
* (int, int) * (int, int)


/** /**
* Was the popup just closed? * Was the popup just closed?
*
*
* @return true if popup was just closed * @return true if popup was just closed
*/ */
public boolean isJustClosed() { public boolean isJustClosed() {


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google * com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google
* .gwt.event.logical.shared.CloseEvent) * .gwt.event.logical.shared.CloseEvent)


/** /**
* Updates style names in suggestion popup to help theme building. * Updates style names in suggestion popup to help theme building.
*
*
* @param uidl * @param uidl
* UIDL for the whole combo box * UIDL for the whole combo box
* @param componentState * @param componentState


/** /**
* Sets the suggestions rendered in the menu * Sets the suggestions rendered in the menu
*
*
* @param suggestions * @param suggestions
* The suggestions to be rendered in the menu * The suggestions to be rendered in the menu
*/ */
/** /**
* TextBox variant used as input element for filter selects, which prevents * TextBox variant used as input element for filter selects, which prevents
* selecting text when disabled. * selecting text when disabled.
*
*
* @since 7.1.5 * @since 7.1.5
*/ */
public class FilterSelectTextBox extends TextBox { public class FilterSelectTextBox extends TextBox {


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt * com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
* .user.client.Event) * .user.client.Event)


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.user.client.ui.Composite#onBrowserEvent(com.google.gwt * com.google.gwt.user.client.ui.Composite#onBrowserEvent(com.google.gwt
* .user.client.Event) * .user.client.Event)
* It is invoked during the Constructor and should only be overridden if a * It is invoked during the Constructor and should only be overridden if a
* custom TextBox shall be used. The overriding method cannot use any * custom TextBox shall be used. The overriding method cannot use any
* instance variables. * instance variables.
*
*
* @since 7.1.5 * @since 7.1.5
* @return TextBox instance used by this VFilterSelect * @return TextBox instance used by this VFilterSelect
*/ */
* instance. It is invoked during the Constructor and should only be * instance. It is invoked during the Constructor and should only be
* overridden if a custom SuggestionPopup shall be used. The overriding * overridden if a custom SuggestionPopup shall be used. The overriding
* method cannot use any instance variables. * method cannot use any instance variables.
*
*
* @since 7.1.5 * @since 7.1.5
* @return SuggestionPopup instance used by this VFilterSelect * @return SuggestionPopup instance used by this VFilterSelect
*/ */


/** /**
* Does the Select have more pages? * Does the Select have more pages?
*
*
* @return true if a next page exists, else false if the current page is the * @return true if a next page exists, else false if the current page is the
* last page * last page
*/ */
/** /**
* Filters the options at a certain page. Uses the text box input as a * Filters the options at a certain page. Uses the text box input as a
* filter * filter
*
*
* @param page * @param page
* The page which items are to be filtered * The page which items are to be filtered
*/ */


/** /**
* Filters the options at certain page using the given filter * Filters the options at certain page using the given filter
*
*
* @param page * @param page
* The page to filter * The page to filter
* @param filter * @param filter


/** /**
* Filters the options at certain page using the given filter * Filters the options at certain page using the given filter
*
*
* @param page * @param page
* The page to filter * The page to filter
* @param filter * @param filter


/** /**
* Sets the text in the text box. * Sets the text in the text box.
*
*
* @param text * @param text
* the text to set in the text box * the text to set in the text box
*/ */
* shown in the text box if nothing has been entered. * shown in the text box if nothing has been entered.
* <p> * <p>
* For internal use only. May be removed or replaced in the future. * For internal use only. May be removed or replaced in the future.
*
*
* @param text * @param text
* The text the text box should contain. * The text the text box should contain.
*/ */


/** /**
* Triggered when a suggestion is selected * Triggered when a suggestion is selected
*
*
* @param suggestion * @param suggestion
* The suggestion that just got selected. * The suggestion that just got selected.
*/ */
/** /**
* Sets the icon URI of the selected item. The icon is shown on the left * 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. * side of the item caption text. Set the URI to null to remove the icon.
*
*
* @param iconUri * @param iconUri
* The URI of the icon * The URI of the icon
*/ */


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt * com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
* .event.dom.client.KeyDownEvent) * .event.dom.client.KeyDownEvent)


/** /**
* Triggered when a key is pressed in the text box * Triggered when a key is pressed in the text box
*
*
* @param event * @param event
* The KeyDownEvent * The KeyDownEvent
*/ */


/** /**
* Triggered when a key was pressed in the suggestion popup. * Triggered when a key was pressed in the suggestion popup.
*
*
* @param event * @param event
* The KeyDownEvent of the key * The KeyDownEvent of the key
*/ */


/** /**
* Triggered when a key was depressed * Triggered when a key was depressed
*
*
* @param event * @param event
* The KeyUpEvent of the key depressed * The KeyUpEvent of the key depressed
*/ */


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
* .dom.client.FocusEvent) * .dom.client.FocusEvent)


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see * @see
* com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
* .dom.client.BlurEvent) * .dom.client.BlurEvent)


/* /*
* (non-Javadoc) * (non-Javadoc)
*
*
* @see com.vaadin.client.Focusable#focus() * @see com.vaadin.client.Focusable#focus()
*/ */


* For internal use only. May be removed or replaced in the future. * For internal use only. May be removed or replaced in the future.
*/ */
public void updateRootWidth() { public void updateRootWidth() {
updateRootWidth(false);
}

/**
* Calculates the width of the select if the select has undefined width.
* Should be called when the width changes or when the icon changes.
* <p>
* For internal use only. May be removed or replaced in the future.
*
* @param forceUpdate
* a flag that forces a recalculation even if one would not
* normally be done
*/
public void updateRootWidth(boolean forceUpdate) {
ComponentConnector paintable = ConnectorMap.get(client).getConnector( ComponentConnector paintable = ConnectorMap.get(client).getConnector(
this); this);

if (paintable.isUndefinedWidth()) { if (paintable.isUndefinedWidth()) {


/* /*
*/ */
int w = Util.getRequiredWidth(this); int w = Util.getRequiredWidth(this);


if (forceUpdate || (!initDone || currentPage + 1 < 0)
if ((!initDone || currentPage + 1 < 0)
&& suggestionPopupMinWidth > w) { && suggestionPopupMinWidth > w) {
/* /*
* We want to compensate for the paddings just to preserve the * We want to compensate for the paddings just to preserve the
String originalBorder = style.getBorderWidth(); String originalBorder = style.getBorderWidth();
style.setPaddingLeft(0, Unit.PX); style.setPaddingLeft(0, Unit.PX);
style.setBorderWidth(0, Unit.PX); style.setBorderWidth(0, Unit.PX);
int offset = w - Util.getRequiredWidth(this);
style.setProperty("padding", originalPadding); style.setProperty("padding", originalPadding);
style.setProperty("borderWidth", originalBorder); style.setProperty("borderWidth", originalBorder);


setWidth(suggestionPopupMinWidth + offset + "px");
// Use util.getRequiredWidth instead of getOffsetWidth here

int iconWidth = selectedItemIcon == null ? 0 : Util
.getRequiredWidth(selectedItemIcon);
int buttonWidth = popupOpener == null ? 0 : Util
.getRequiredWidth(popupOpener);

/*
* Instead of setting the width of the wrapper, set the width of
* the combobox. Subtract the width of the icon and the
* popupopener
*/

tb.setWidth((suggestionPopupMinWidth - iconWidth - buttonWidth)
+ "px");

} }


/* /*
/** /**
* Get the width of the select in pixels where the text area and icon has * Get the width of the select in pixels where the text area and icon has
* been included. * been included.
*
*
* @return The width in pixels * @return The width in pixels
*/ */
private int getMainWidth() { private int getMainWidth() {


/** /**
* Handles special behavior of the mouse down event * Handles special behavior of the mouse down event
*
*
* @param event * @param event
*/ */
private void handleMouseDownEvent(Event event) { private void handleMouseDownEvent(Event event) {

+ 3
- 24
client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java View File

import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.Paintable; import com.vaadin.client.Paintable;
import com.vaadin.client.UIDL; import com.vaadin.client.UIDL;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.SimpleManagedLayout; import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.ui.VFilterSelect; import com.vaadin.client.ui.VFilterSelect;
// update textbox text by a changed item caption. // update textbox text by a changed item caption.
private boolean oldSuggestionTextMatchTheOldSelection; private boolean oldSuggestionTextMatchTheOldSelection;


// Need to recompute the width of the combobox when styles change, see
// #13444
private boolean stylesChanged;

/* /*
* (non-Javadoc) * (non-Javadoc)
* *
getWidget().popupOpenerClicked = false; getWidget().popupOpenerClicked = false;


/* /*
* if styles have changed or this is our first time we need to
* recalculate the root width.
* if this is our first time we need to recalculate the root width.
*/ */
if (!getWidget().initDone) { if (!getWidget().initDone) {
// no need to force update since we have no existing width
getWidget().updateRootWidth(false);
} else if (stylesChanged) {
// we have previously calculated a width, we must force an update
// due to changed styles
getWidget().updateRootWidth(true);

getWidget().updateRootWidth();
} }


// Focus dependent style names are lost during the update, so we add // Focus dependent style names are lost during the update, so we add
getWidget().addStyleDependentName("focus"); getWidget().addStyleDependentName("focus");
} }


// width has been recalculated above, clear style change flag
stylesChanged = false;

getWidget().initDone = true; getWidget().initDone = true;
} }


getWidget().tb.setEnabled(widgetEnabled); getWidget().tb.setEnabled(widgetEnabled);
} }


@Override
public void onStateChanged(StateChangeEvent event) {
super.onStateChanged(event);
if (event.hasPropertyChanged("styles")) {
stylesChanged = true;
}
}

} }

Loading…
Cancel
Save