| /* |
| * Copyright 2010 Google Inc. |
| * |
| * 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.google.gwt.user.client.ui; |
| |
| import com.google.gwt.dom.client.Document; |
| import com.google.gwt.dom.client.NativeEvent; |
| import com.google.gwt.junit.DoNotRunWith; |
| import com.google.gwt.junit.Platform; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| |
| /** |
| * Tests for {@link SplitLayoutPanel}. |
| */ |
| public class SplitLayoutPanelTest extends DockLayoutPanelTest { |
| |
| static class Adder implements HasWidgetsTester.WidgetAdder { |
| @Override |
| public void addChild(HasWidgets container, Widget child) { |
| ((SplitLayoutPanel) container).addNorth(child, 10); |
| } |
| } |
| |
| public void testAttachDetachOrder() { |
| HasWidgetsTester.testAll(new SplitLayoutPanel(), new Adder(), true); |
| } |
| |
| public void testReplaceCenterWidget() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| Label l0 = new Label("foo"); |
| Label l1 = new Label("bar"); |
| Label l2 = new Label("baz"); |
| |
| // center: l1 |
| p.addWest(l0, 64); |
| p.add(l1); |
| assertEquals(l1, p.getCenter()); |
| |
| // center: l2 |
| p.remove(l1); |
| p.add(l2); |
| assertEquals(l2, p.getCenter()); |
| } |
| |
| public void testSetWidgetMinSizeCenter() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| Label west = new Label("west"); |
| Label center = new Label("center"); |
| |
| p.addWest(west, 100); |
| p.add(center); |
| |
| // Should be ignored gracefully. |
| p.setWidgetMinSize(center, 10); |
| } |
| |
| public void testSplitterOrder() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| WidgetCollection children = p.getChildren(); |
| |
| Label l0 = new Label("foo"); |
| Label l1 = new Label("bar"); |
| Label l2 = new Label("baz"); |
| Label l3 = new Label("tintin"); |
| Label l4 = new Label("toto"); |
| |
| p.addWest(l0, 64); |
| assertEquals(l0, children.get(0)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass()); |
| |
| p.addNorth(l1, 64); |
| assertEquals(l1, children.get(2)); |
| assertEquals(SplitLayoutPanel.VSplitter.class, children.get(3).getClass()); |
| |
| p.addEast(l2, 64); |
| assertEquals(l2, children.get(4)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(5).getClass()); |
| |
| p.addSouth(l3, 64); |
| assertEquals(l3, children.get(6)); |
| assertEquals(SplitLayoutPanel.VSplitter.class, children.get(7).getClass()); |
| |
| p.add(l4); |
| assertEquals(l4, children.get(8)); |
| } |
| |
| public void testSplitterSize() { |
| SplitLayoutPanel p = new SplitLayoutPanel(5); |
| assertEquals(5, p.getSplitterSize()); |
| WidgetCollection children = p.getChildren(); |
| |
| p.addWest(new Label("foo"), 64); |
| assertEquals("5px", |
| children.get(1).getElement().getStyle().getWidth().toLowerCase(Locale.ROOT)); |
| } |
| |
| public void testRemoveInsert() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| WidgetCollection children = p.getChildren(); |
| |
| Label l0 = new Label("foo"); |
| Label l1 = new Label("bar"); |
| Label l2 = new Label("baz"); |
| |
| p.addWest(l0, 64); |
| p.add(l1); |
| assertEquals(l0, children.get(0)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass()); |
| assertEquals(l1, children.get(2)); |
| |
| p.remove(l0); |
| p.insertWest(l2, 64, l1); |
| assertEquals(l2, children.get(0)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass()); |
| assertEquals(l1, children.get(2)); |
| } |
| |
| public void testRemoveOutOfOrder() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| WidgetCollection children = p.getChildren(); |
| |
| Label l0 = new Label("foo"); |
| Label l1 = new Label("bar"); |
| |
| p.addWest(l0, 64); |
| p.addWest(l1, 64); |
| assertEquals(l0, children.get(0)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(1).getClass()); |
| assertEquals(l1, children.get(2)); |
| assertEquals(SplitLayoutPanel.HSplitter.class, children.get(3).getClass()); |
| |
| SplitLayoutPanel.HSplitter splitter0 = (SplitLayoutPanel.HSplitter) children.get(1); |
| |
| // Remove the second element and make sure the correct splitter is removed. |
| p.remove(l1); |
| assertEquals(2, children.size()); |
| assertEquals(l0, children.get(0)); |
| assertEquals(splitter0, children.get(1)); |
| } |
| |
| @DoNotRunWith({Platform.HtmlUnitLayout}) |
| public void testResize() { |
| SplitLayoutPanel p = new SplitLayoutPanel(); |
| RootLayoutPanel.get().add(p); |
| |
| // RootLayoutPanel handles setting the size automatically, but it's deferred to the document |
| // onLoad event, so we'd have to run the whole rest of this test in a deferred command to use |
| // that. (Otherwise, Element#getClientHeight always returns 0, since nothing's been rendered.) |
| // Setting some absolute heights on the panel manually lets us run the test synchronously. |
| p.setHeight("1000px"); |
| p.setWidth("1000px"); |
| |
| Label north = new Label("north"); |
| Label south = new Label("south"); |
| Label east = new Label("east"); |
| Label west = new Label("west"); |
| |
| p.addNorth(north, 100); |
| p.addSouth(south, 200); |
| p.addEast(east, 300); |
| p.addWest(west, 400); |
| p.forceLayout(); |
| |
| WidgetCollection children = p.getChildren(); |
| Widget northSplitter = children.get(1); |
| assertEquals(SplitLayoutPanel.VSplitter.class, northSplitter.getClass()); |
| Widget southSplitter = children.get(3); |
| assertEquals(SplitLayoutPanel.VSplitter.class, southSplitter.getClass()); |
| Widget eastSplitter = children.get(5); |
| assertEquals(SplitLayoutPanel.HSplitter.class, eastSplitter.getClass()); |
| Widget westSplitter = children.get(7); |
| assertEquals(SplitLayoutPanel.HSplitter.class, westSplitter.getClass()); |
| |
| // Dragging the north splitter down 10px should increase the north size from 100px -> 110px. |
| assertEquals(100, north.getOffsetHeight()); |
| dragSplitter(northSplitter, 0, 10); |
| p.forceLayout(); |
| assertEquals(110, north.getOffsetHeight()); |
| |
| // Dragging the south splitter up 10px should increase the south size from 200px -> 210px. |
| assertEquals(200, south.getOffsetHeight()); |
| dragSplitter(southSplitter, 0, -10); |
| p.forceLayout(); |
| assertEquals(210, south.getOffsetHeight()); |
| |
| // Dragging the east splitter right 10px should decrease the east size from 300px -> 290px. |
| assertEquals(300, east.getOffsetWidth()); |
| dragSplitter(eastSplitter, 10, 0); |
| p.forceLayout(); |
| assertEquals(290, east.getOffsetWidth()); |
| |
| // Dragging the west splitter left 10px should decrease the west size from 400px -> 390px. |
| assertEquals(400, west.getOffsetWidth()); |
| dragSplitter(westSplitter, -10, 0); |
| p.forceLayout(); |
| assertEquals(390, west.getOffsetWidth()); |
| } |
| |
| /** |
| * Test that forcing layout will call onResize only once. |
| */ |
| public void testForceLayoutNoRedundantOnResize() { |
| final List<Boolean> called = new ArrayList<>(); |
| SplitLayoutPanel panel = new SplitLayoutPanel(); |
| SimpleLayoutPanel child = new SimpleLayoutPanel() { |
| @Override |
| public void onResize() { |
| super.onResize(); |
| called.add(true); |
| } |
| }; |
| panel.addWest(child,123.4); |
| panel.forceLayout(); |
| assertEquals(1,called.size()); |
| } |
| |
| @Override |
| protected DockLayoutPanel createDockLayoutPanel() { |
| return new SplitLayoutPanel(); |
| } |
| |
| /** Simulates a mouse drag on a splitter widget by creating and dispatching native events. */ |
| private void dragSplitter(Widget splitter, int offsetX, int offsetY) { |
| // Even though the actual splitters are at various places in the document, all these mouse |
| // drags start at 0,0. The panel calculates the "offset" between the actual position and the |
| // mouse position, and compensates for that; if that logic is correct, then the actual |
| // positions shouldn't matter, only the relative movement since the mouse down event. |
| // |
| // This is important in some cases where the browser window is scrolled -- see issue 4755. |
| NativeEvent mouseDown = Document.get().createMouseDownEvent( |
| 0, /* detail */ |
| 0, 0, /* screen X, Y */ |
| 0, 0, /* client X, Y */ |
| false, false, false, false, /* modifier keys */ |
| NativeEvent.BUTTON_LEFT); |
| splitter.getElement().dispatchEvent(mouseDown); |
| |
| NativeEvent mouseMove = Document.get().createMouseMoveEvent( |
| 0, |
| offsetX, offsetY, |
| offsetX, offsetY, |
| false, false, false, false, |
| NativeEvent.BUTTON_LEFT); |
| splitter.getElement().dispatchEvent(mouseMove); |
| |
| NativeEvent mouseUp = Document.get().createMouseUpEvent( |
| 0, |
| offsetX, offsetY, |
| offsetX, offsetY, |
| false, false, false, false, |
| NativeEvent.BUTTON_LEFT); |
| splitter.getElement().dispatchEvent(mouseUp); |
| } |
| } |