aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorFelype Santiago Ferreira <felype@vaadin.com>2014-02-26 16:05:37 +0200
committerVaadin Code Review <review@vaadin.com>2014-04-08 06:34:55 +0000
commitf32e3535c6ef73bca33f274e9906f57aa178d22a (patch)
treeba2453a82f97a2c68f35d363ed2c553d84d5bae9 /client
parentef8920661cc9d958c69cfedd0a74ce580a2a84ed (diff)
downloadvaadin-framework-f32e3535c6ef73bca33f274e9906f57aa178d22a.tar.gz
vaadin-framework-f32e3535c6ef73bca33f274e9906f57aa178d22a.zip
Update Accordion and TabSheet to use Vaadin 7 style. (#13402).
This change also adds subpart support for TabSheet and converts a test to TB3. Change-Id: I23b6c81686ea6587470d8019e89a85149ec0b068
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ui/VAccordion.java162
-rw-r--r--client/src/com/vaadin/client/ui/VTabsheet.java316
-rw-r--r--client/src/com/vaadin/client/ui/VTabsheetBase.java100
-rw-r--r--client/src/com/vaadin/client/ui/accordion/AccordionConnector.java59
-rw-r--r--client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java69
-rw-r--r--client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java74
6 files changed, 472 insertions, 308 deletions
diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java
index eb8cb8b2ed..cba08d8e6b 100644
--- a/client/src/com/vaadin/client/ui/VAccordion.java
+++ b/client/src/com/vaadin/client/ui/VAccordion.java
@@ -15,7 +15,6 @@
*/
package com.vaadin.client.ui;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -28,43 +27,41 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.ConnectorMap;
-import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
-import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants;
-import com.vaadin.shared.ui.tabsheet.TabsheetConstants;
+import com.vaadin.shared.ComponentConstants;
+import com.vaadin.shared.ui.accordion.AccordionState;
+import com.vaadin.shared.ui.tabsheet.TabState;
+import com.vaadin.shared.ui.tabsheet.TabsheetServerRpc;
public class VAccordion extends VTabsheetBase {
- public static final String CLASSNAME = "v-accordion";
+ public static final String CLASSNAME = AccordionState.PRIMARY_STYLE_NAME;
private Set<Widget> widgets = new HashSet<Widget>();
- /** For internal use only. May be removed or replaced in the future. */
- public HashMap<StackItem, UIDL> lazyUpdateMap = new HashMap<StackItem, UIDL>();
-
- private StackItem openTab = null;
+ private StackItem openTab;
/** For internal use only. May be removed or replaced in the future. */
- public int selectedUIDLItemIndex = -1;
+ public int selectedItemIndex = -1;
private final TouchScrollHandler touchScrollHandler;
public VAccordion() {
super(CLASSNAME);
+
touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
}
@Override
- public void renderTab(UIDL tabUidl, int index, boolean selected,
- boolean hidden) {
+ public void renderTab(TabState tabState, int index) {
StackItem item;
int itemIndex;
+
if (getWidgetCount() <= index) {
// Create stackItem and render caption
- item = new StackItem(tabUidl);
+ item = new StackItem();
if (getWidgetCount() == 0) {
item.addStyleDependentName("first");
}
@@ -72,23 +69,19 @@ public class VAccordion extends VTabsheetBase {
add(item, getElement());
} else {
item = getStackItem(index);
- item = moveStackItemIfNeeded(item, index, tabUidl);
+
itemIndex = index;
}
- item.updateCaption(tabUidl);
+ item.updateCaption(tabState);
- item.updateTabStyleName(tabUidl
- .getStringAttribute(TabsheetConstants.TAB_STYLE_NAME));
+ item.updateTabStyleName(tabState.styleName);
- item.setVisible(!hidden);
-
- if (selected) {
- selectedUIDLItemIndex = itemIndex;
- }
+ item.setVisible(tabState.visible);
+ }
- if (tabUidl.getChildCount() > 0) {
- lazyUpdateMap.put(item, tabUidl.getChildUIDL(0));
- }
+ @Override
+ public void selectTab(int index) {
+ selectedItemIndex = index;
}
@Override
@@ -112,69 +105,6 @@ public class VAccordion extends VTabsheetBase {
}
}
- /**
- * This method tries to find out if a tab has been rendered with a different
- * index previously. If this is the case it re-orders the children so the
- * same StackItem is used for rendering this time. E.g. if the first tab has
- * been removed all tabs which contain cached content must be moved 1 step
- * up to preserve the cached content.
- *
- * @param item
- * @param newIndex
- * @param tabUidl
- * @return
- */
- private StackItem moveStackItemIfNeeded(StackItem item, int newIndex,
- UIDL tabUidl) {
- UIDL tabContentUIDL = null;
- ComponentConnector tabContent = null;
- if (tabUidl.getChildCount() > 0) {
- tabContentUIDL = tabUidl.getChildUIDL(0);
- tabContent = client.getPaintable(tabContentUIDL);
- }
-
- Widget itemWidget = item.getComponent();
- if (tabContent != null) {
- if (tabContent.getWidget() != itemWidget) {
- /*
- * This is not the same widget as before, find out if it has
- * been moved
- */
- int oldIndex = -1;
- StackItem oldItem = null;
- for (int i = 0; i < getWidgetCount(); i++) {
- Widget w = getWidget(i);
- oldItem = (StackItem) w;
- if (tabContent == oldItem.getComponent()) {
- oldIndex = i;
- break;
- }
- }
-
- if (oldIndex != -1 && oldIndex > newIndex) {
- /*
- * The tab has previously been rendered in another position
- * so we must move the cached content to correct position.
- * We move only items with oldIndex > newIndex to prevent
- * moving items already rendered in this update. If for
- * instance tabs 1,2,3 are removed and added as 3,2,1 we
- * cannot re-use "1" when we get to the third tab.
- */
- insert(oldItem, getElement(), newIndex, true);
- return oldItem;
- }
- }
- } else {
- // Tab which has never been loaded. Must assure we use an empty
- // StackItem
- Widget oldWidget = item.getComponent();
- if (oldWidget != null) {
- oldWidget.removeFromParent();
- }
- }
- return item;
- }
-
/** For internal use only. May be removed or replaced in the future. */
public void open(int itemIndex) {
StackItem item = (StackItem) getWidget(itemIndex);
@@ -210,10 +140,14 @@ public class VAccordion extends VTabsheetBase {
public void onSelectTab(StackItem item) {
final int index = getWidgetIndex(item);
+
if (index != activeTabIndex && !disabled && !readonly
&& !disabledTabKeys.contains(tabKeys.get(index))) {
+
addStyleDependentName("loading");
- client.updateVariable(id, "selected", "" + tabKeys.get(index), true);
+
+ connector.getRpcProxy(TabsheetServerRpc.class).setSelected(
+ tabKeys.get(index).toString());
}
}
@@ -296,7 +230,7 @@ public class VAccordion extends VTabsheetBase {
private Element captionNode = DOM.createDiv();
private String styleName;
- public StackItem(UIDL tabUidl) {
+ public StackItem() {
setElement(DOM.createDiv());
caption = new VCaption(client);
caption.addClickHandler(this);
@@ -375,10 +309,17 @@ public class VAccordion extends VTabsheetBase {
return open;
}
- public void setContent(UIDL contentUidl) {
- final ComponentConnector newPntbl = client
- .getPaintable(contentUidl);
- Widget newWidget = newPntbl.getWidget();
+ /**
+ * Updates the content of the open tab of the accordion.
+ *
+ * This method is mostly for internal use and may change in future
+ * versions.
+ *
+ * @since 7.2
+ * @param newWidget
+ * new content
+ */
+ public void setContent(Widget newWidget) {
if (getChildWidget() == null) {
add(newWidget, content);
widgets.add(newWidget);
@@ -395,14 +336,19 @@ public class VAccordion extends VTabsheetBase {
onSelectTab(this);
}
- public void updateCaption(UIDL uidl) {
+ public void updateCaption(TabState tabState) {
// TODO need to call this because the caption does not have an owner
caption.updateCaptionWithoutOwner(
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_CAPTION),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE),
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ICON));
+ tabState.caption,
+ !tabState.enabled,
+ hasAttribute(tabState.description),
+ hasAttribute(tabState.componentError),
+ connector.getResourceUrl(ComponentConstants.ICON_RESOURCE
+ + tabState.key));
+ }
+
+ private boolean hasAttribute(String string) {
+ return string != null && !string.trim().isEmpty();
}
/**
@@ -450,18 +396,6 @@ public class VAccordion extends VTabsheetBase {
clear();
}
- boolean isDynamicWidth() {
- ComponentConnector paintable = ConnectorMap.get(client).getConnector(
- this);
- return paintable.isUndefinedWidth();
- }
-
- boolean isDynamicHeight() {
- ComponentConnector paintable = ConnectorMap.get(client).getConnector(
- this);
- return paintable.isUndefinedHeight();
- }
-
@Override
public Iterator<Widget> getWidgetIterator() {
return widgets.iterator();
@@ -488,7 +422,7 @@ public class VAccordion extends VTabsheetBase {
}
Widget w = stackItem.getChildWidget();
if (w != null) {
- return ConnectorMap.get(client).getConnector(w);
+ return getConnectorForWidget(w);
}
}
diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java
index 4da5e4bfe0..f2e4003e7f 100644
--- a/client/src/com/vaadin/client/ui/VTabsheet.java
+++ b/client/src/com/vaadin/client/ui/VTabsheet.java
@@ -43,6 +43,8 @@ import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
@@ -53,21 +55,23 @@ import com.google.gwt.user.client.ui.impl.FocusImpl;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.TooltipInfo;
-import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
+import com.vaadin.client.VTooltip;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.EventId;
+import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.ComponentStateUtil;
-import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants;
-import com.vaadin.shared.ui.tabsheet.TabsheetConstants;
+import com.vaadin.shared.ui.tabsheet.TabState;
+import com.vaadin.shared.ui.tabsheet.TabsheetServerRpc;
+import com.vaadin.shared.ui.tabsheet.TabsheetState;
public class VTabsheet extends VTabsheetBase implements Focusable,
- FocusHandler, BlurHandler, KeyDownHandler {
+ FocusHandler, BlurHandler, KeyDownHandler, SubPartAware {
private static class VCloseEvent {
private Tab tab;
@@ -140,8 +144,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
DOM.appendChild(td, div);
- tabCaption = new TabCaption(this, getTabsheet()
- .getApplicationConnection());
+ tabCaption = new TabCaption(this);
add(tabCaption);
Roles.getTabRole().setAriaLabelledbyProperty(getElement(),
@@ -228,12 +231,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
return tabBar.getTabsheet();
}
- public void updateFromUIDL(UIDL tabUidl) {
- tabCaption.updateCaption(tabUidl);
-
+ private void updateFromState(TabState tabState) {
+ tabCaption.update(tabState);
// Apply the styleName set for the tab
- String newStyleName = tabUidl
- .getStringAttribute(TabsheetConstants.TAB_STYLE_NAME);
+ String newStyleName = tabState.styleName;
// Find the nth td element
if (newStyleName != null && !newStyleName.isEmpty()) {
if (!newStyleName.equals(styleName)) {
@@ -253,7 +254,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
styleName = null;
}
- String newId = tabUidl.getStringAttribute("id");
+ String newId = tabState.id;
if (newId != null && !newId.isEmpty()) {
td.setId(newId);
id = newId;
@@ -315,38 +316,45 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
private Element closeButton;
private Tab tab;
- TabCaption(Tab tab, ApplicationConnection client) {
- super(client);
+ TabCaption(Tab tab) {
+ super(tab.getTabsheet().connector.getConnection());
this.tab = tab;
AriaHelper.ensureHasId(getElement());
}
- public boolean updateCaption(UIDL uidl) {
- if (uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION)
- || uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE)) {
- setTooltipInfo(new TooltipInfo(
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION),
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE)));
+ private boolean update(TabState tabState) {
+ if (tabState.description != null
+ || tabState.componentError != null) {
+ setTooltipInfo(new TooltipInfo(tabState.description,
+ tabState.componentError));
} else {
setTooltipInfo(null);
}
// TODO need to call this instead of super because the caption does
// not have an owner
- boolean ret = updateCaptionWithoutOwner(
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_CAPTION),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DESCRIPTION),
- uidl.hasAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ERROR_MESSAGE),
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ICON),
- uidl.getStringAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_ICON_ALT));
-
- setClosable(uidl.hasAttribute("closable"));
+ String captionString = tabState.caption.isEmpty() ? null
+ : tabState.caption;
+ boolean ret = updateCaptionWithoutOwner(captionString,
+ !tabState.enabled,
+ hasAttribute(tabState.description),
+ hasAttribute(tabState.componentError),
+ tab.getTabsheet().connector
+ .getResourceUrl(ComponentConstants.ICON_RESOURCE
+ + tabState.key),
+ tabState.iconAltText
+ );
+
+ setClosable(tabState.closable);
return ret;
}
+ private boolean hasAttribute(String string) {
+ return string != null && !string.trim().isEmpty();
+ }
+
private VTabsheet getTabsheet() {
return tab.getTabsheet();
}
@@ -637,12 +645,21 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
currentFirst.recalculateCaptionWidth();
return nextVisible;
}
+
+ private void recalculateCaptionWidths() {
+ for (int i = 0; i < getTabCount(); ++i) {
+ getTab(i).recalculateCaptionWidth();
+ }
+ }
}
- public static final String CLASSNAME = "v-tabsheet";
+ // TODO using the CLASSNAME directly makes primaryStyleName for TabSheet of
+ // very limited use - all use of style names should be refactored in the
+ // future
+ public static final String CLASSNAME = TabsheetState.PRIMARY_STYLE_NAME;
- public static final String TABS_CLASSNAME = "v-tabsheet-tabcontainer";
- public static final String SCROLLER_CLASSNAME = "v-tabsheet-scroller";
+ public static final String TABS_CLASSNAME = CLASSNAME + "-tabcontainer";
+ public static final String SCROLLER_CLASSNAME = CLASSNAME + "-scroller";
/** For internal use only. May be removed or replaced in the future. */
// tabbar and 'scroller' container
@@ -670,7 +687,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
final TabBar tb = new TabBar(this);
/** For internal use only. May be removed or replaced in the future. */
- public final VTabsheetPanel tp = new VTabsheetPanel();
+ protected final VTabsheetPanel tabPanel = new VTabsheetPanel();
/** For internal use only. May be removed or replaced in the future. */
public final Element contentNode;
@@ -681,12 +698,16 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
private String currentStyle;
+ /** For internal use only. May be removed or replaced in the future. */
+ private int focusedTabIndex = 0;
+
/**
* @return Whether the tab could be selected or not.
*/
private boolean canSelectTab(final int tabIndex) {
Tab tab = tb.getTab(tabIndex);
- if (client == null || disabled || waitingForResponse) {
+ if (getApplicationConnection() == null || disabled
+ || waitingForResponse) {
return false;
}
if (!tab.isEnabledOnServer() || tab.isHiddenOnServer()) {
@@ -713,22 +734,56 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
addStyleDependentName("loading");
// Hide the current contents so a loading indicator can be shown
// instead
- Widget currentlyDisplayedWidget = tp.getWidget(tp
- .getVisibleWidget());
- currentlyDisplayedWidget.getElement().getParentElement().getStyle()
- .setVisibility(Visibility.HIDDEN);
- client.updateVariable(id, "selected", tabKeys.get(tabIndex)
- .toString(), true);
+ getCurrentlyDisplayedWidget().getElement().getParentElement()
+ .getStyle().setVisibility(Visibility.HIDDEN);
+
+ getRpcProxy().setSelected(tabKeys.get(tabIndex).toString());
+
waitingForResponse = true;
tb.getTab(tabIndex).focus(); // move keyboard focus to active tab
}
}
+ /**
+ * Returns the currently displayed widget in the tab panel.
+ *
+ * @since 7.2
+ * @return currently displayed content widget
+ */
+ public Widget getCurrentlyDisplayedWidget() {
+ return tabPanel.getWidget(tabPanel.getVisibleWidget());
+ }
+
+ /**
+ * Returns the client to server RPC proxy for the tabsheet.
+ *
+ * @since 7.2
+ * @return RPC proxy
+ */
+ protected TabsheetServerRpc getRpcProxy() {
+ return connector.getRpcProxy(TabsheetServerRpc.class);
+ }
+
+ /**
+ * For internal use only.
+ *
+ * Avoid using this method directly and use appropriate superclass methods
+ * where applicable.
+ *
+ * @deprecated since 7.2 - use more specific methods instead (getRpcProxy(),
+ * getConnectorForWidget(Widget) etc.)
+ * @return ApplicationConnection
+ */
+ @Deprecated
public ApplicationConnection getApplicationConnection() {
return client;
}
+ private VTooltip getVTooltip() {
+ return getApplicationConnection().getVTooltip();
+ }
+
public void tabSizeMightHaveChanged(Tab tab) {
// icon onloads may change total width of tabsheet
if (isDynamicWidth()) {
@@ -739,19 +794,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
void sendTabClosedEvent(int tabIndex) {
- client.updateVariable(id, "close", tabKeys.get(tabIndex), true);
- }
-
- boolean isDynamicWidth() {
- ComponentConnector paintable = ConnectorMap.get(client).getConnector(
- this);
- return paintable.isUndefinedWidth();
- }
-
- boolean isDynamicHeight() {
- ComponentConnector paintable = ConnectorMap.get(client).getConnector(
- this);
- return paintable.isUndefinedHeight();
+ getRpcProxy().closeTab(tabKeys.get(tabIndex));
}
public VTabsheet() {
@@ -785,7 +828,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
DOM.appendChild(getElement(), tabs);
// Tabs
- tp.setStyleName(CLASSNAME + "-tabsheetpanel");
+ tabPanel.setStyleName(CLASSNAME + "-tabsheetpanel");
contentNode = DOM.createDiv();
Roles.getTabpanelRole().set(contentNode);
@@ -801,7 +844,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
DOM.appendChild(scroller, scrollerNext);
DOM.appendChild(getElement(), contentNode);
- add(tp, contentNode);
+ add(tabPanel, contentNode);
DOM.appendChild(getElement(), deco);
DOM.appendChild(tabs, scroller);
@@ -851,7 +894,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
/** For internal use only. May be removed or replaced in the future. */
- public void handleStyleNames(UIDL uidl, AbstractComponentState state) {
+ public void handleStyleNames(AbstractComponentState state) {
// Add proper stylenames for all elements (easier to prevent unwanted
// style inheritance)
if (ComponentStateUtil.hasStyles(state)) {
@@ -882,14 +925,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
+ "-content");
DOM.setElementProperty(deco, "className", CLASSNAME + "-deco");
}
-
- if (uidl.hasAttribute("hidetabs")) {
- tb.setVisible(false);
- addStyleName(CLASSNAME + "-hidetabs");
- } else {
- tb.setVisible(true);
- removeStyleName(CLASSNAME + "-hidetabs");
- }
}
/** For internal use only. May be removed or replaced in the future. */
@@ -906,16 +941,16 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
int tabsWidth = tb.getOffsetWidth() - spacerWidth + spacerMinWidth;
// Find content width
- Style style = tp.getElement().getStyle();
+ Style style = tabPanel.getElement().getStyle();
String overflow = style.getProperty("overflow");
style.setProperty("overflow", "hidden");
style.setPropertyPx("width", tabsWidth);
- boolean hasTabs = tp.getWidgetCount() > 0;
+ boolean hasTabs = tabPanel.getWidgetCount() > 0;
Style wrapperstyle = null;
if (hasTabs) {
- wrapperstyle = tp.getWidget(tp.getVisibleWidget()).getElement()
+ wrapperstyle = getCurrentlyDisplayedWidget().getElement()
.getParentElement().getStyle();
wrapperstyle.setPropertyPx("width", tabsWidth);
}
@@ -923,7 +958,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
int contentWidth = 0;
if (hasTabs) {
- contentWidth = tp.getWidget(tp.getVisibleWidget()).getOffsetWidth();
+ contentWidth = getCurrentlyDisplayedWidget().getOffsetWidth();
}
style.setProperty("overflow", overflow);
@@ -946,26 +981,22 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
@Override
- public void renderTab(final UIDL tabUidl, int index, boolean selected,
- boolean hidden) {
+ public void renderTab(final TabState tabState, int index) {
Tab tab = tb.getTab(index);
if (tab == null) {
tab = tb.addTab();
}
- if (selected) {
- tb.selectTab(index);
- renderContent(tabUidl.getChildUIDL(0));
- }
- tab.updateFromUIDL(tabUidl);
+
+ tab.updateFromState(tabState);
tab.setEnabledOnServer((!disabledTabKeys.contains(tabKeys.get(index))));
- tab.setHiddenOnServer(hidden);
+ tab.setHiddenOnServer(!tabState.visible);
if (scrolledOutOfView(index)) {
// Should not set tabs visible if they are scrolled out of view
- hidden = true;
+ tabState.visible = false;
}
// Set the current visibility of the tab (in the browser)
- tab.setVisible(!hidden);
+ tab.setVisible(tabState.visible);
/*
* Force the width of the caption container so the content will not wrap
@@ -985,23 +1016,29 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
}
- private void renderContent(final UIDL contentUIDL) {
- final ComponentConnector content = client.getPaintable(contentUIDL);
- Widget newWidget = content.getWidget();
+ /**
+ * Renders the widget content for a tab sheet.
+ *
+ * @param newWidget
+ */
+ public void renderContent(Widget newWidget) {
+ assert tabPanel.getWidgetCount() <= 1;
- assert tp.getWidgetCount() <= 1;
+ if (null == newWidget) {
+ newWidget = new SimplePanel();
+ }
- if (tp.getWidgetCount() == 0) {
- tp.add(newWidget);
- } else if (tp.getWidget(0) != newWidget) {
- tp.remove(0);
- tp.add(newWidget);
+ if (tabPanel.getWidgetCount() == 0) {
+ tabPanel.add(newWidget);
+ } else if (tabPanel.getWidget(0) != newWidget) {
+ tabPanel.remove(0);
+ tabPanel.add(newWidget);
}
- assert tp.getWidgetCount() <= 1;
+ assert tabPanel.getWidgetCount() <= 1;
// There's never any other index than 0, but maintaining API for now
- tp.showWidget(0);
+ tabPanel.showWidget(0);
VTabsheet.this.iLayout();
updateOpenTabSize();
@@ -1058,7 +1095,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
*/
minWidth = tb.getOffsetWidth() - getContentAreaBorderWidth();
}
- tp.fixVisibleTabSize(width, height, minWidth);
+ tabPanel.fixVisibleTabSize(width, height, minWidth);
}
@@ -1149,13 +1186,13 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
while (i > 0) {
tb.removeTab(--i);
}
- tp.clear();
+ tabPanel.clear();
}
@Override
public Iterator<Widget> getWidgetIterator() {
- return tp.iterator();
+ return tabPanel.iterator();
}
private int borderW = -1;
@@ -1175,9 +1212,9 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
@Override
public ComponentConnector getTab(int index) {
- if (tp.getWidgetCount() > index) {
- Widget widget = tp.getWidget(index);
- return ConnectorMap.get(client).getConnector(widget);
+ if (tabPanel.getWidgetCount() > index) {
+ Widget widget = tabPanel.getWidget(index);
+ return getConnectorForWidget(widget);
}
return null;
}
@@ -1190,14 +1227,19 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
@Override
+ public void selectTab(int index) {
+ tb.selectTab(index);
+ }
+
+ @Override
public void onBlur(BlurEvent event) {
- getApplicationConnection().getVTooltip().hideTooltip();
+ getVTooltip().hideTooltip();
if (focusedTab != null && focusedTab == event.getSource()) {
focusedTab.removeAssistiveDescription();
focusedTab = null;
- if (client.hasEventListeners(this, EventId.BLUR)) {
- client.updateVariable(id, EventId.BLUR, "", true);
+ if (connector.hasEventListener(EventId.BLUR)) {
+ connector.getRpcProxy(FocusAndBlurServerRpc.class).blur();
}
}
}
@@ -1206,15 +1248,13 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
public void onFocus(FocusEvent event) {
if (focusedTab == null && event.getSource() instanceof Tab) {
focusedTab = (Tab) event.getSource();
- if (client.hasEventListeners(this, EventId.FOCUS)) {
- client.updateVariable(id, EventId.FOCUS, "", true);
+ if (connector.hasEventListener(EventId.FOCUS)) {
+ connector.getRpcProxy(FocusAndBlurServerRpc.class).focus();
}
if (focusedTab.hasTooltip()) {
- focusedTab.setAssistiveDescription(getApplicationConnection()
- .getVTooltip().getUniqueId());
- getApplicationConnection().getVTooltip().showAssistive(
- focusedTab.getTooltipInfo());
+ focusedTab.setAssistiveDescription(getVTooltip().getUniqueId());
+ getVTooltip().showAssistive(focusedTab.getTooltipInfo());
}
}
}
@@ -1336,4 +1376,70 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
}
}
+
+ /**
+ * Makes tab bar visible.
+ *
+ * @since 7.2
+ */
+ public void showTabs() {
+ tb.setVisible(true);
+ removeStyleName(CLASSNAME + "-hidetabs");
+ tb.recalculateCaptionWidths();
+ }
+
+ /**
+ * Makes tab bar invisible.
+ *
+ * @since 7.2
+ */
+ public void hideTabs() {
+ tb.setVisible(false);
+ addStyleName(CLASSNAME + "-hidetabs");
+ }
+
+ /** Matches tab[ix] - used for extracting the index of the targeted tab */
+ private static final RegExp SUBPART_TAB_REGEXP = RegExp
+ .compile("tab\\[(\\d+)](.*)");
+
+ @Override
+ public com.google.gwt.user.client.Element getSubPartElement(String subPart) {
+ if ("tabpanel".equals(subPart)) {
+ return DOM.asOld(tabPanel.getElement().getFirstChildElement());
+ } else if (SUBPART_TAB_REGEXP.test(subPart)) {
+ MatchResult result = SUBPART_TAB_REGEXP.exec(subPart);
+ int tabIx = Integer.valueOf(result.getGroup(1));
+ Tab tab = tb.getTab(tabIx);
+ if (tab != null) {
+ if ("/close".equals(result.getGroup(2))) {
+ if (tab.isClosable()) {
+ return tab.tabCaption.getCloseButton();
+ }
+ } else {
+ return tab.tabCaption.getElement();
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getSubPartName(com.google.gwt.user.client.Element subElement) {
+ if (tabPanel.getElement().equals(subElement.getParentElement())
+ || tabPanel.getElement().equals(subElement)) {
+ return "tabpanel";
+ } else {
+ for (int i = 0; i < tb.getTabCount(); ++i) {
+ Tab tab = tb.getTab(i);
+ if (tab.isClosable()
+ && tab.tabCaption.getCloseButton().isOrHasChild(
+ subElement)) {
+ return "tab[" + i + "]/close";
+ } else if (tab.getElement().isOrHasChild(subElement)) {
+ return "tab[" + i + "]";
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/client/src/com/vaadin/client/ui/VTabsheetBase.java b/client/src/com/vaadin/client/ui/VTabsheetBase.java
index bcd8811c7d..6d9f78e87f 100644
--- a/client/src/com/vaadin/client/ui/VTabsheetBase.java
+++ b/client/src/com/vaadin/client/ui/VTabsheetBase.java
@@ -25,28 +25,28 @@ import com.google.gwt.user.client.ui.ComplexPanel;
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.ConnectorMap;
+import com.vaadin.shared.ui.tabsheet.TabState;
public abstract class VTabsheetBase extends ComplexPanel {
/** For internal use only. May be removed or replaced in the future. */
- public String id;
- /** For internal use only. May be removed or replaced in the future. */
- public ApplicationConnection client;
+ protected ApplicationConnection client;
/** For internal use only. May be removed or replaced in the future. */
- public final ArrayList<String> tabKeys = new ArrayList<String>();
+ protected final ArrayList<String> tabKeys = new ArrayList<String>();
/** For internal use only. May be removed or replaced in the future. */
- public Set<String> disabledTabKeys = new HashSet<String>();
+ protected Set<String> disabledTabKeys = new HashSet<String>();
/** For internal use only. May be removed or replaced in the future. */
- public int activeTabIndex = 0;
+ protected int activeTabIndex = 0;
/** For internal use only. May be removed or replaced in the future. */
- public int focusedTabIndex = 0;
+ protected boolean disabled;
/** For internal use only. May be removed or replaced in the future. */
- public boolean disabled;
+ protected boolean readonly;
+
/** For internal use only. May be removed or replaced in the future. */
- public boolean readonly;
+ protected AbstractComponentConnector connector;
public VTabsheetBase(String classname) {
setElement(DOM.createDiv());
@@ -61,14 +61,13 @@ public abstract class VTabsheetBase extends ComplexPanel {
/**
* Clears current tabs and contents
*/
- abstract protected void clearPaintables();
+ protected abstract void clearPaintables();
/**
* Implement in extending classes. This method should render needed elements
* and set the visibility of the tab according to the 'selected' parameter.
*/
- public abstract void renderTab(final UIDL tabUidl, int index,
- boolean selected, boolean hidden);
+ public abstract void renderTab(TabState tabState, int index);
/**
* Implement in extending classes. This method should return the number of
@@ -87,4 +86,79 @@ public abstract class VTabsheetBase extends ComplexPanel {
* tab with the specified index.
*/
public abstract void removeTab(int index);
+
+ /**
+ * Returns true if the width of the widget is undefined, false otherwise.
+ *
+ * @since 7.2
+ * @return true if width of the widget is determined by its content
+ */
+ protected boolean isDynamicWidth() {
+ return getConnectorForWidget(this).isUndefinedWidth();
+ }
+
+ /**
+ * Returns true if the height of the widget is undefined, false otherwise.
+ *
+ * @since 7.2
+ * @return true if width of the height is determined by its content
+ */
+ protected boolean isDynamicHeight() {
+ return getConnectorForWidget(this).isUndefinedHeight();
+ }
+
+ /**
+ * Sets the connector that should be notified of events etc.
+ *
+ * For internal use only. This method may be removed or replaced in the
+ * future.
+ *
+ * @since 7.2
+ * @param connector
+ */
+ public void setConnector(AbstractComponentConnector connector) {
+ this.connector = connector;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void clearTabKeys() {
+ tabKeys.clear();
+ disabledTabKeys.clear();
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void addTabKey(String key, boolean disabled) {
+ tabKeys.add(key);
+ if (disabled) {
+ disabledTabKeys.add(key);
+ }
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setClient(ApplicationConnection client) {
+ this.client = client;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setActiveTabIndex(int activeTabIndex) {
+ this.activeTabIndex = activeTabIndex;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setEnabled(boolean enabled) {
+ disabled = !enabled;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public void setReadonly(boolean readonly) {
+ this.readonly = readonly;
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ protected ComponentConnector getConnectorForWidget(Widget widget) {
+ return ConnectorMap.get(client).getConnector(widget);
+ }
+
+ /** For internal use only. May be removed or replaced in the future. */
+ public abstract void selectTab(int index);
}
diff --git a/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java b/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java
index 99fbd07f9b..ce843dc22f 100644
--- a/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java
+++ b/client/src/com/vaadin/client/ui/accordion/AccordionConnector.java
@@ -15,19 +15,17 @@
*/
package com.vaadin.client.ui.accordion;
-import java.util.Iterator;
-
-import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
-import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.ui.VAccordion;
import com.vaadin.client.ui.VAccordion.StackItem;
import com.vaadin.client.ui.layout.MayScrollChildren;
import com.vaadin.client.ui.tabsheet.TabsheetBaseConnector;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.accordion.AccordionState;
import com.vaadin.ui.Accordion;
@Connect(Accordion.class)
@@ -35,35 +33,32 @@ public class AccordionConnector extends TabsheetBaseConnector implements
SimpleManagedLayout, MayScrollChildren {
@Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidget().selectedUIDLItemIndex = -1;
- super.updateFromUIDL(uidl, client);
+ protected void init() {
+ super.init();
+ getWidget().setConnector(this);
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
/*
* Render content after all tabs have been created and we know how large
* the content area is
*/
- if (getWidget().selectedUIDLItemIndex >= 0) {
+ if (getWidget().selectedItemIndex >= 0) {
StackItem selectedItem = getWidget().getStackItem(
- getWidget().selectedUIDLItemIndex);
- UIDL selectedTabUIDL = getWidget().lazyUpdateMap
- .remove(selectedItem);
- getWidget().open(getWidget().selectedUIDLItemIndex);
+ getWidget().selectedItemIndex);
- selectedItem.setContent(selectedTabUIDL);
- } else if (isRealUpdate(uidl) && getWidget().getOpenStackItem() != null) {
- getWidget().close(getWidget().getOpenStackItem());
- }
+ getWidget().open(getWidget().selectedItemIndex);
- // finally render possible hidden tabs
- if (getWidget().lazyUpdateMap.size() > 0) {
- for (Iterator iterator = getWidget().lazyUpdateMap.keySet()
- .iterator(); iterator.hasNext();) {
- StackItem item = (StackItem) iterator.next();
- item.setContent(getWidget().lazyUpdateMap.get(item));
+ ComponentConnector contentConnector = getChildComponents().get(0);
+ if (contentConnector != null) {
+ selectedItem.setContent(contentConnector.getWidget());
}
- getWidget().lazyUpdateMap.clear();
+ } else if (getWidget().getOpenStackItem() != null) {
+ getWidget().close(getWidget().getOpenStackItem());
}
-
}
@Override
@@ -123,14 +118,24 @@ public class AccordionConnector extends TabsheetBaseConnector implements
openTab.setHeight(spaceForOpenItem);
} else {
openTab.setHeightFromWidget();
-
}
-
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ConnectorHierarchyChangeEvent.
+ * ConnectorHierarchyChangeHandler
+ * #onConnectorHierarchyChange(com.vaadin.client
+ * .ConnectorHierarchyChangeEvent)
+ */
@Override
public void onConnectorHierarchyChange(
ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) {
- // TODO Move code from updateFromUIDL to this method
+ }
+
+ @Override
+ public AccordionState getState() {
+ return (AccordionState) super.getState();
}
}
diff --git a/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java b/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
index 283bc1b63b..30c9e47c6e 100644
--- a/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
+++ b/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
@@ -19,31 +19,41 @@ import java.util.ArrayList;
import java.util.Iterator;
import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.Paintable;
-import com.vaadin.client.UIDL;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentContainerConnector;
import com.vaadin.client.ui.VTabsheetBase;
-import com.vaadin.shared.ui.tabsheet.TabsheetBaseConstants;
+import com.vaadin.shared.ui.tabsheet.TabState;
+import com.vaadin.shared.ui.tabsheet.TabsheetState;
public abstract class TabsheetBaseConnector extends
- AbstractComponentContainerConnector implements Paintable {
+ AbstractComponentContainerConnector {
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.client.ui.AbstractConnector#init()
+ */
@Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- getWidget().client = client;
+ protected void init() {
+ super.init();
- if (!isRealUpdate(uidl)) {
- return;
- }
+ getWidget().setClient(getConnection());
+ }
- // Update member references
- getWidget().id = uidl.getId();
- getWidget().disabled = !isEnabled();
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ui.AbstractComponentConnector#onStateChanged(com.vaadin
+ * .client.communication.StateChangeEvent)
+ */
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
- // Render content
- final UIDL tabs = uidl.getChildUIDL(0);
+ // Update member references
+ getWidget().setEnabled(isEnabled());
// Widgets in the TabSheet before update
ArrayList<Widget> oldWidgets = new ArrayList<Widget>();
@@ -53,26 +63,22 @@ public abstract class TabsheetBaseConnector extends
}
// Clear previous values
- getWidget().tabKeys.clear();
- getWidget().disabledTabKeys.clear();
+ getWidget().clearTabKeys();
int index = 0;
- for (final Iterator<Object> it = tabs.getChildIterator(); it.hasNext();) {
- final UIDL tab = (UIDL) it.next();
- final String key = tab.getStringAttribute("key");
- final boolean selected = tab.getBooleanAttribute("selected");
- final boolean hidden = tab.getBooleanAttribute("hidden");
-
- if (tab.getBooleanAttribute(TabsheetBaseConstants.ATTRIBUTE_TAB_DISABLED)) {
- getWidget().disabledTabKeys.add(key);
- }
+ for (TabState tab : getState().tabs) {
+ final String key = tab.key;
+ final boolean selected = key.equals(getState().selected);
- getWidget().tabKeys.add(key);
+ getWidget().addTabKey(key, !tab.enabled && tab.visible);
if (selected) {
- getWidget().activeTabIndex = index;
+ getWidget().setActiveTabIndex(index);
+ }
+ getWidget().renderTab(tab, index);
+ if (selected) {
+ getWidget().selectTab(index);
}
- getWidget().renderTab(tab, index, selected, hidden);
index++;
}
@@ -104,4 +110,9 @@ public abstract class TabsheetBaseConnector extends
return (VTabsheetBase) super.getWidget();
}
+ @Override
+ public TabsheetState getState() {
+ return (TabsheetState) super.getState();
+ }
+
}
diff --git a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
index 608ed1e139..b472300c21 100644
--- a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
+++ b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java
@@ -17,36 +17,62 @@ package com.vaadin.client.ui.tabsheet;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
-import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.TooltipInfo;
-import com.vaadin.client.UIDL;
import com.vaadin.client.Util;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.ui.VTabsheet;
import com.vaadin.client.ui.layout.MayScrollChildren;
import com.vaadin.shared.ui.Connect;
-import com.vaadin.shared.ui.tabsheet.TabsheetState;
+import com.vaadin.shared.ui.tabsheet.TabsheetClientRpc;
import com.vaadin.ui.TabSheet;
@Connect(TabSheet.class)
public class TabsheetConnector extends TabsheetBaseConnector implements
SimpleManagedLayout, MayScrollChildren {
- // Can't use "style" as it's already in use
+ public TabsheetConnector() {
+ registerRpc(TabsheetClientRpc.class, new TabsheetClientRpc() {
+ @Override
+ public void revertToSharedStateSelection() {
+ for (int i = 0; i < getState().tabs.size(); ++i) {
+ final String key = getState().tabs.get(i).key;
+ final boolean selected = key.equals(getState().selected);
+ if (selected) {
+ getWidget().selectTab(i);
+ break;
+ }
+ }
+ renderContent();
+ }
+ });
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ getWidget().setConnector(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.client.ui.AbstractComponentConnector#onStateChanged(com.vaadin
+ * .client.communication.StateChangeEvent)
+ */
@Override
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
- if (isRealUpdate(uidl)) {
- // Handle stylename changes before generics (might affect size
- // calculations)
- getWidget().handleStyleNames(uidl, getState());
- }
+ getWidget().handleStyleNames(getState());
- super.updateFromUIDL(uidl, client);
- if (!isRealUpdate(uidl)) {
- return;
+ if (getState().tabsVisible) {
+ getWidget().showTabs();
+ } else {
+ getWidget().hideTabs();
}
// tabs; push or not
@@ -76,11 +102,6 @@ public class TabsheetConnector extends TabsheetBaseConnector implements
}
@Override
- public TabsheetState getState() {
- return (TabsheetState) super.getState();
- }
-
- @Override
public void updateCaption(ComponentConnector component) {
/* Tabsheet does not render its children's captions */
}
@@ -147,7 +168,20 @@ public class TabsheetConnector extends TabsheetBaseConnector implements
@Override
public void onConnectorHierarchyChange(
- ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) {
- // TODO Move code from updateFromUIDL to this method
+ ConnectorHierarchyChangeEvent connector) {
+ renderContent();
+ }
+
+ /**
+ * (Re-)render the content of the active tab.
+ */
+ protected void renderContent() {
+ ComponentConnector contentConnector = getChildComponents().get(0);
+ if (null != contentConnector) {
+ getWidget().renderContent(contentConnector.getWidget());
+ } else {
+ getWidget().renderContent(null);
+ }
}
+
}