diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/src/main/java/com/vaadin/client/ui/VTabsheet.java | 139 |
1 files changed, 127 insertions, 12 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VTabsheet.java b/client/src/main/java/com/vaadin/client/ui/VTabsheet.java index 123f89bb36..82f805db8f 100644 --- a/client/src/main/java/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/main/java/com/vaadin/client/ui/VTabsheet.java @@ -16,8 +16,10 @@ package com.vaadin.client.ui; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import com.google.gwt.aria.client.Id; import com.google.gwt.aria.client.LiveValue; @@ -272,6 +274,9 @@ public class VTabsheet extends VTabsheetBase public void recalculateCaptionWidth() { tabCaption.setWidth(tabCaption.getRequiredWidth() + "px"); + if (isVisible()) { + tabBar.tabWidths.put(this, getOffsetWidth()); + } } @Override @@ -443,6 +448,9 @@ public class VTabsheet extends VTabsheetBase private VTabsheet tabsheet; + /** For internal use only. May be removed or replaced in the future. */ + private Map<Tab, Integer> tabWidths = new HashMap<Tab, Integer>(); + TabBar(VTabsheet tabsheet) { this.tabsheet = tabsheet; @@ -502,6 +510,7 @@ public class VTabsheet extends VTabsheetBase getTabsheet().selectionHandler.registerTab(t); t.setCloseHandler(this); + tabWidths.put(t, t.getOffsetWidth()); return t; } @@ -522,6 +531,18 @@ public class VTabsheet extends VTabsheetBase return (Tab) super.getWidget(index); } + private int getTabIndex(Tab tab) { + if (tab == null) { + return -1; + } + for (int i = 0; i < getTabCount(); i++) { + if (tab.equals(getTab(i))) { + return i; + } + } + return -1; + } + private int getTabIndex(String tabId) { if (tabId == null) { return -1; @@ -593,6 +614,7 @@ public class VTabsheet extends VTabsheetBase } remove(tab); + tabWidths.remove(tab); /* * If this widget was selected we need to unmark it as the last @@ -616,6 +638,13 @@ public class VTabsheet extends VTabsheetBase } } + private int getLastKnownTabWidth(Tab tab) { + if (tabWidths.containsKey(tab)) { + return tabWidths.get(tab); + } + return 0; + } + private int selectNewShownTab(int oldPosition) { // After removing a tab, find a new scroll position. In most // cases the scroll position does not change, but if the tab @@ -686,6 +715,13 @@ public class VTabsheet extends VTabsheetBase } /** + * Returns the index of the last visible tab on the server + */ + private int getLastVisibleTab() { + return getPreviousVisibleTab(getTabCount()); + } + + /** * Find the previous visible tab. Returns -1 if none is found. * * @param i @@ -702,7 +738,7 @@ public class VTabsheet extends VTabsheetBase public int scrollLeft(int currentFirstVisible) { int prevVisible = getPreviousVisibleTab(currentFirstVisible); - if (prevVisible == -1) { + if (prevVisible < 0) { return -1; } @@ -715,7 +751,7 @@ public class VTabsheet extends VTabsheetBase public int scrollRight(int currentFirstVisible) { int nextVisible = getNextVisibleTab(currentFirstVisible); - if (nextVisible == -1) { + if (nextVisible < 0) { return -1; } Tab currentFirst = getTab(currentFirstVisible); @@ -1335,14 +1371,44 @@ public class VTabsheet extends VTabsheetBase scrollerIndex = tb.getNextVisibleTab(scrollerIndex); } + TableCellElement spacerCell = ((TableElement) tb.getElement().cast()) + .getRows().getItem(0).getCells().getItem(tb.getTabCount()); + if (scroller.getStyle().getDisplay() != "none") { + spacerCell.getStyle().setPropertyPx("minWidth", + scroller.getOffsetWidth()); + spacerCell.getStyle().setPropertyPx("minHeight", 1); + } else { + spacerCell.getStyle().setProperty("minWidth", "0"); + spacerCell.getStyle().setProperty("minHeight", "0"); + } + + // check if hidden tabs need to be scrolled back into view + int firstVisibleIndex = tb.getFirstVisibleTabClient(); + if (firstVisibleIndex != 0 && getTabCount() > 0 + && getLeftGap() + getRightGap() > 0) { + int hiddenCount = tb.getTabCount(); + if (firstVisibleIndex > 0) { + hiddenCount -= firstVisibleIndex; + } + int counter = 0; + while ((getLeftGap() + getRightGap() > getFirstOutOfViewWidth()) + && counter < hiddenCount) { + tb.scrollLeft(tb.getFirstVisibleTabClient()); + scrollerIndex = tb.getFirstVisibleTabClient(); + ++counter; + } + } + boolean scrolled = isScrolledTabs(); boolean clipped = isClippedTabs(); if (tb.getTabCount() > 0 && tb.isVisible() && (scrolled || clipped)) { scroller.getStyle().clearDisplay(); - DOM.setElementProperty(scrollerPrev, "className", SCROLLER_CLASSNAME + scrollerPrev.setPropertyString("className", SCROLLER_CLASSNAME + (scrolled ? "Prev" : PREV_SCROLLER_DISABLED_CLASSNAME)); - DOM.setElementProperty(scrollerNext, "className", - SCROLLER_CLASSNAME + (clipped ? "Next" : "Next-disabled")); + scrollerNext.setPropertyString("className", + SCROLLER_CLASSNAME + (clipped + && scrollerIndex != tb.getLastVisibleTab() ? "Next" + : "Next-disabled")); // the active tab should be focusable if and only if it is visible boolean isActiveTabVisible = scrollerIndex <= activeTabIndex @@ -1367,6 +1433,48 @@ public class VTabsheet extends VTabsheetBase } } + private int getLeftGap() { + int firstVisibleIndex = tb.getFirstVisibleTabClient(); + int gap; + if (firstVisibleIndex < 0) { + // no tabs are visible, the entire empty space is returned + // through getRightGap() + gap = 0; + } else { + Element tabContainer = tb.getElement().getParentElement(); + Tab firstVisibleTab = tb.getTab(firstVisibleIndex); + gap = firstVisibleTab.getAbsoluteLeft() + - tabContainer.getAbsoluteLeft(); + } + return gap > 0 ? gap : 0; + } + + private int getRightGap() { + int lastVisibleIndex = tb.getLastVisibleTab(); + Element tabContainer = tb.getElement().getParentElement(); + int gap; + if (lastVisibleIndex < 0) { + // no tabs visible, return the whole available width + gap = getOffsetWidth() - scroller.getOffsetWidth(); + } else { + Tab lastVisibleTab = tb.getTab(lastVisibleIndex); + gap = tabContainer.getAbsoluteRight() + - lastVisibleTab.getAbsoluteLeft() + - lastVisibleTab.getOffsetWidth() + - scroller.getOffsetWidth() - 2; + } + return gap > 0 ? gap : 0; + } + + private int getFirstOutOfViewWidth() { + Tab firstTabOutOfView = tb.getTab( + tb.getPreviousVisibleTab(tb.getFirstVisibleTabClient())); + if (firstTabOutOfView != null) { + return tb.getLastKnownTabWidth(firstTabOutOfView); + } + return 0; + } + /** For internal use only. May be removed or replaced in the future. */ public void showAllTabs() { scrollerIndex = tb.getFirstVisibleTab(); @@ -1385,10 +1493,8 @@ public class VTabsheet extends VTabsheetBase } private boolean isClippedTabs() { - return (tb.getOffsetWidth() - DOM.getElementPropertyInt( - (Element) tb.getContainerElement().getLastChild().cast(), - "offsetWidth")) > getOffsetWidth() - - (isScrolledTabs() ? scroller.getOffsetWidth() : 0); + return (tb.getOffsetWidth() - getSpacerWidth()) > getOffsetWidth() + - (isScrolledTabs() ? scroller.getOffsetWidth() : 0); } private boolean isClipped(Tab tab) { @@ -1396,6 +1502,12 @@ public class VTabsheet extends VTabsheetBase + getOffsetWidth() - scroller.getOffsetWidth(); } + private int getSpacerWidth() { + int spacerWidth = ((Element) tb.getContainerElement().getLastChild() + .cast()).getPropertyInt("offsetWidth"); + return spacerWidth; + } + @Override protected void clearPaintables() { @@ -1934,13 +2046,16 @@ public class VTabsheet extends VTabsheetBase // On IE8 a tab with false visibility would have the bounds of the // full TabBar. if (!tab.isVisible()) { - while (!tab.isVisible()) { + while (!tab.isVisible() && scrollerIndex > 0) { scrollerIndex = tb.scrollLeft(scrollerIndex); } updateTabScroller(); - } else if (isClipped(tab)) { - while (isClipped(tab) && scrollerIndex != -1) { + } else if (isClipped(tab) + && scrollerIndex < tb.getLastVisibleTab()) { + int tabIndex = tb.getTabIndex(tab); + while (isClipped(tab) && scrollerIndex >= 0 + && scrollerIndex < tabIndex) { scrollerIndex = tb.scrollRight(scrollerIndex); } updateTabScroller(); |