Add setting to control whether tree items are scrolled into view when selected. Adapted from patch http://gwt-code-reviews.appspot.com/1819803/ Credit for the original patch goes to Marko Krajnc (marko.krajnc@cursor.si) Fixes issue 2467. Review by: mdempsky@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11465 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/Tree.java b/user/src/com/google/gwt/user/client/ui/Tree.java index a83796c..5d062a5 100644 --- a/user/src/com/google/gwt/user/client/ui/Tree.java +++ b/user/src/com/google/gwt/user/client/ui/Tree.java
@@ -243,6 +243,8 @@ private TreeItem root; + private boolean scrollOnSelectEnabled = true; + private boolean useLeafImages; /** @@ -635,6 +637,13 @@ return isAnimationEnabled; } + /** + * Determines whether selecting a tree item will scroll it into view. + */ + public boolean isScrollOnSelectEnabled() { + return scrollOnSelectEnabled; + } + @Override public Iterator<Widget> iterator() { final Widget[] widgets = new Widget[childWidgets.size()]; @@ -853,6 +862,14 @@ } /** + * Enable or disable scrolling a tree item into view when it is selected. Scrolling into view is + * enabled by default. + */ + public void setScrollOnSelectEnabled(boolean enable) { + scrollOnSelectEnabled = enable; + } + + /** * Selects a specified item. * * @param item the item to be selected, or <code>null</code> to deselect all @@ -1221,35 +1238,39 @@ Focusable focusableWidget = curSelection.getFocusable(); if (focusableWidget != null) { focusableWidget.setFocus(true); - DOM.scrollIntoView(((Widget) focusableWidget).getElement()); - } else { - // Get the location and size of the given item's content element relative - // to the tree. - Element selectedElem = curSelection.getContentElem(); - int containerLeft = getAbsoluteLeft(); - int containerTop = getAbsoluteTop(); - - int left = DOM.getAbsoluteLeft(selectedElem) - containerLeft; - int top = DOM.getAbsoluteTop(selectedElem) - containerTop; - int width = DOM.getElementPropertyInt(selectedElem, "offsetWidth"); - int height = DOM.getElementPropertyInt(selectedElem, "offsetHeight"); - - // If the item is not visible, quite here - if (width == 0 || height == 0) { - DOM.setIntStyleAttribute(focusable, "left", 0); - DOM.setIntStyleAttribute(focusable, "top", 0); - return; + if (scrollOnSelectEnabled) { + DOM.scrollIntoView(((Widget) focusableWidget).getElement()); } + } else { + if (scrollOnSelectEnabled) { + // Get the location and size of the given item's content element relative + // to the tree. + Element selectedElem = curSelection.getContentElem(); + int containerLeft = getAbsoluteLeft(); + int containerTop = getAbsoluteTop(); + + int left = DOM.getAbsoluteLeft(selectedElem) - containerLeft; + int top = DOM.getAbsoluteTop(selectedElem) - containerTop; + int width = DOM.getElementPropertyInt(selectedElem, "offsetWidth"); + int height = DOM.getElementPropertyInt(selectedElem, "offsetHeight"); - // Set the focusable element's position and size to exactly underlap the - // item's content element. - DOM.setStyleAttribute(focusable, "left", left + "px"); - DOM.setStyleAttribute(focusable, "top", top + "px"); - DOM.setStyleAttribute(focusable, "width", width + "px"); - DOM.setStyleAttribute(focusable, "height", height + "px"); - - // Scroll it into view. - DOM.scrollIntoView(focusable); + // If the item is not visible, quite here + if (width == 0 || height == 0) { + DOM.setIntStyleAttribute(focusable, "left", 0); + DOM.setIntStyleAttribute(focusable, "top", 0); + return; + } + + // Set the focusable element's position and size to exactly underlap the + // item's content element. + DOM.setStyleAttribute(focusable, "left", left + "px"); + DOM.setStyleAttribute(focusable, "top", top + "px"); + DOM.setStyleAttribute(focusable, "width", width + "px"); + DOM.setStyleAttribute(focusable, "height", height + "px"); + + // Scroll it into view. + DOM.scrollIntoView(focusable); + } // Update ARIA attributes to reflect the information from the // newly-selected item.
diff --git a/user/test/com/google/gwt/user/client/ui/TreeTest.java b/user/test/com/google/gwt/user/client/ui/TreeTest.java index 212b901..dfcda3a 100644 --- a/user/test/com/google/gwt/user/client/ui/TreeTest.java +++ b/user/test/com/google/gwt/user/client/ui/TreeTest.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.user.client.ui; +import com.google.gwt.junit.DoNotRunWith; +import com.google.gwt.junit.Platform; import com.google.gwt.junit.client.GWTTestCase; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.user.client.DOM; @@ -344,6 +346,55 @@ // Expected. } } + + @DoNotRunWith(Platform.HtmlUnitLayout) + public void testScrollOnSelectEnabledFalse() { + // With scrolling disabled. + Tree tree = createTree(); + tree.setScrollOnSelectEnabled(false); + assertScrollingOnSelection(tree, false); + } + + @DoNotRunWith(Platform.HtmlUnitLayout) + public void testScrollOnSelectEnabledTrue() { + // With scrolling enabled (default) + Tree tree = createTree(); + assertTrue(tree.isScrollOnSelectEnabled()); + assertScrollingOnSelection(tree, true); + } + + private void assertScrollingOnSelection(Tree tree, boolean shouldScroll) { + tree.addItem(new Label("hello1")); + tree.addItem(new Label("hello2")); + TreeItem levelZeroTreeItem = tree.addItem(new Label("level0")); + TreeItem selectedItem = levelZeroTreeItem.addItem(new Label("level1")); + selectedItem.addItem(SafeHtmlUtils.fromString("level2")); + + // For the tree to be opened. Otherwise, all sizes will be zero and no scrolling would occur, + // regardless of the mode. + levelZeroTreeItem.setState(true); + selectedItem.setState(true); + + ScrollPanel panel = new ScrollPanel(); + RootPanel.get().add(panel); + panel.setWidget(tree); + + // Set a size that is smaller than the content to allow scrolling + panel.setPixelSize(40, 90); + + assertEquals(0, panel.getVerticalScrollPosition()); + assertEquals(0, panel.getHorizontalScrollPosition()); + + tree.setSelectedItem(selectedItem); + + if (shouldScroll) { + assertTrue("Expected vertical scroll", panel.getVerticalScrollPosition() != 0); + assertTrue("Expected horizontal scroll", panel.getHorizontalScrollPosition() != 0); + } else { + assertEquals("Expected no vertical scroll", 0, panel.getVerticalScrollPosition()); + assertEquals("Expected no horizontal scroll", 0, panel.getHorizontalScrollPosition()); + } + } public void testSwap() { Tree t = createTree();