123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /*
- * Copyright 2000-2013 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.client.ui;
-
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Set;
-
- import com.google.gwt.event.dom.client.ClickEvent;
- import com.google.gwt.event.dom.client.ClickHandler;
- import com.google.gwt.user.client.DOM;
- 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;
-
- public class VAccordion extends VTabsheetBase {
-
- public static final String CLASSNAME = "v-accordion";
-
- 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;
-
- /** For internal use only. May be removed or replaced in the future. */
- public int selectedUIDLItemIndex = -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) {
- StackItem item;
- int itemIndex;
- if (getWidgetCount() <= index) {
- // Create stackItem and render caption
- item = new StackItem(tabUidl);
- if (getWidgetCount() == 0) {
- item.addStyleDependentName("first");
- }
- itemIndex = getWidgetCount();
- add(item, getElement());
- } else {
- item = getStackItem(index);
- item = moveStackItemIfNeeded(item, index, tabUidl);
- itemIndex = index;
- }
- item.updateCaption(tabUidl);
-
- item.updateTabStyleName(tabUidl
- .getStringAttribute(TabsheetConstants.TAB_STYLE_NAME));
-
- item.setVisible(!hidden);
-
- if (selected) {
- selectedUIDLItemIndex = itemIndex;
- }
-
- if (tabUidl.getChildCount() > 0) {
- lazyUpdateMap.put(item, tabUidl.getChildUIDL(0));
- }
- }
-
- @Override
- public void setStylePrimaryName(String style) {
- super.setStylePrimaryName(style);
- updateStyleNames(style);
- }
-
- @Override
- public void setStyleName(String style) {
- super.setStyleName(style);
- updateStyleNames(style);
- }
-
- protected void updateStyleNames(String primaryStyleName) {
- for (Widget w : getChildren()) {
- if (w instanceof StackItem) {
- StackItem item = (StackItem) w;
- item.updateStyleNames(primaryStyleName);
- }
- }
- }
-
- /**
- * 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);
- boolean alreadyOpen = false;
- if (openTab != null) {
- if (openTab.isOpen()) {
- if (openTab == item) {
- alreadyOpen = true;
- } else {
- openTab.close();
- }
- }
- }
- if (!alreadyOpen) {
- item.open();
- activeTabIndex = itemIndex;
- openTab = item;
- }
-
- }
-
- /** For internal use only. May be removed or replaced in the future. */
- public void close(StackItem item) {
- if (!item.isOpen()) {
- return;
- }
-
- item.close();
- activeTabIndex = -1;
- openTab = null;
-
- }
-
- 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);
- }
- }
-
- /**
- * A StackItem has always two children, Child 0 is a VCaption, Child 1 is
- * the actual child widget.
- */
- public class StackItem extends ComplexPanel implements ClickHandler {
-
- public void setHeight(int height) {
- if (height == -1) {
- super.setHeight("");
- DOM.setStyleAttribute(content, "height", "0px");
- } else {
- super.setHeight((height + getCaptionHeight()) + "px");
- DOM.setStyleAttribute(content, "height", height + "px");
- DOM.setStyleAttribute(content, "top", getCaptionHeight() + "px");
-
- }
- }
-
- public Widget getComponent() {
- if (getWidgetCount() < 2) {
- return null;
- }
- return getWidget(1);
- }
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- }
-
- public void setHeightFromWidget() {
- Widget widget = getChildWidget();
- if (widget == null) {
- return;
- }
-
- int paintableHeight = widget.getElement().getOffsetHeight();
- setHeight(paintableHeight);
-
- }
-
- /**
- * Returns caption width including padding
- *
- * @return
- */
- public int getCaptionWidth() {
- if (caption == null) {
- return 0;
- }
-
- int captionWidth = caption.getRequiredWidth();
- int padding = Util.measureHorizontalPaddingAndBorder(
- caption.getElement(), 18);
- return captionWidth + padding;
- }
-
- public void setWidth(int width) {
- if (width == -1) {
- super.setWidth("");
- } else {
- super.setWidth(width + "px");
- }
- }
-
- public int getHeight() {
- return getOffsetHeight();
- }
-
- public int getCaptionHeight() {
- return captionNode.getOffsetHeight();
- }
-
- private VCaption caption;
- private boolean open = false;
- private com.google.gwt.user.client.Element content = DOM.createDiv();
- private com.google.gwt.user.client.Element captionNode = DOM
- .createDiv();
- private String styleName;
-
- public StackItem(UIDL tabUidl) {
- setElement(DOM.createDiv());
- caption = new VCaption(client);
- caption.addClickHandler(this);
- super.add(caption, captionNode);
- DOM.appendChild(captionNode, caption.getElement());
- DOM.appendChild(getElement(), captionNode);
- DOM.appendChild(getElement(), content);
-
- updateStyleNames(VAccordion.this.getStylePrimaryName());
-
- touchScrollHandler.addElement(getContainerElement());
-
- close();
- }
-
- private void updateStyleNames(String primaryStyleName) {
- content.removeClassName(getStylePrimaryName() + "-content");
- captionNode.removeClassName(getStylePrimaryName() + "-caption");
-
- setStylePrimaryName(primaryStyleName + "-item");
- updateTabStyleName(getStylePrimaryName());
-
- captionNode.addClassName(getStylePrimaryName() + "-caption");
- content.addClassName(getStylePrimaryName() + "-content");
- }
-
- @Override
- public void onBrowserEvent(Event event) {
- onSelectTab(this);
- }
-
- public com.google.gwt.user.client.Element getContainerElement() {
- return content;
- }
-
- public Widget getChildWidget() {
- if (getWidgetCount() > 1) {
- return getWidget(1);
- } else {
- return null;
- }
- }
-
- public void replaceWidget(Widget newWidget) {
- if (getWidgetCount() > 1) {
- Widget oldWidget = getWidget(1);
- widgets.remove(oldWidget);
- }
- add(newWidget, content);
- widgets.add(newWidget);
- }
-
- public void open() {
- open = true;
- DOM.setStyleAttribute(content, "top", getCaptionHeight() + "px");
- DOM.setStyleAttribute(content, "left", "0px");
- DOM.setStyleAttribute(content, "visibility", "");
- addStyleDependentName("open");
- }
-
- public void hide() {
- DOM.setStyleAttribute(content, "visibility", "hidden");
- }
-
- public void close() {
- DOM.setStyleAttribute(content, "visibility", "hidden");
- DOM.setStyleAttribute(content, "top", "-100000px");
- DOM.setStyleAttribute(content, "left", "-100000px");
- removeStyleDependentName("open");
- setHeight(-1);
- setWidth("");
- open = false;
- }
-
- public boolean isOpen() {
- return open;
- }
-
- public void setContent(UIDL contentUidl) {
- final ComponentConnector newPntbl = client
- .getPaintable(contentUidl);
- Widget newWidget = newPntbl.getWidget();
- if (getChildWidget() == null) {
- add(newWidget, content);
- widgets.add(newWidget);
- } else if (getChildWidget() != newWidget) {
- replaceWidget(newWidget);
- }
- if (isOpen() && isDynamicHeight()) {
- setHeightFromWidget();
- }
- }
-
- @Override
- public void onClick(ClickEvent event) {
- onSelectTab(this);
- }
-
- public void updateCaption(UIDL uidl) {
- // 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));
- }
-
- /**
- * Updates a tabs stylename from the child UIDL
- *
- * @param uidl
- * The child uidl of the tab
- */
- private void updateTabStyleName(String newStyleName) {
- if (newStyleName != null && newStyleName.length() != 0) {
- if (!newStyleName.equals(styleName)) {
- // If we have a new style name
- if (styleName != null && styleName.length() != 0) {
- // Remove old style name if present
- removeStyleDependentName(styleName);
- }
- // Set new style name
- addStyleDependentName(newStyleName);
- styleName = newStyleName;
- }
- } else if (styleName != null) {
- // Remove the set stylename if no stylename is present in the
- // uidl
- removeStyleDependentName(styleName);
- styleName = null;
- }
- }
-
- public int getWidgetWidth() {
- return DOM.getFirstChild(content).getOffsetWidth();
- }
-
- public boolean contains(ComponentConnector p) {
- return (getChildWidget() == p.getWidget());
- }
-
- public boolean isCaptionVisible() {
- return caption.isVisible();
- }
-
- }
-
- @Override
- protected void clearPaintables() {
- 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();
- }
-
- @Override
- public int getTabCount() {
- return getWidgetCount();
- }
-
- @Override
- public void removeTab(int index) {
- StackItem item = getStackItem(index);
- remove(item);
- touchScrollHandler.removeElement(item.getContainerElement());
- }
-
- @Override
- public ComponentConnector getTab(int index) {
- if (index < getWidgetCount()) {
- StackItem stackItem = getStackItem(index);
- if (stackItem == null) {
- return null;
- }
- Widget w = stackItem.getChildWidget();
- if (w != null) {
- return ConnectorMap.get(client).getConnector(w);
- }
- }
-
- return null;
- }
-
- /** For internal use only. May be removed or replaced in the future. */
- public StackItem getStackItem(int index) {
- return (StackItem) getWidget(index);
- }
-
- public Iterable<StackItem> getStackItems() {
- return (Iterable) getChildren();
- }
-
- public StackItem getOpenStackItem() {
- return openTab;
- }
-
- }
|