Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

Fix toolbar overflow (JDK-8152395) #318

Merged
merged 12 commits into from Jan 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -453,21 +453,27 @@ public CssMetaData<ToolBar,Pos> getCssMetaData() {
// super.layoutChildren();
final ToolBar toolbar = getSkinnable();

double toolbarLength = getToolbarLength(toolbar);
if (toolbar.getOrientation() == Orientation.VERTICAL) {
if (snapSizeY(toolbar.getHeight()) != previousHeight || needsUpdate) {
((VBox)box).setSpacing(getSpacing());
((VBox)box).setAlignment(getBoxAlignment());
previousHeight = snapSizeY(toolbar.getHeight());
addNodesToToolBar();
} else {
correctOverflow(toolbarLength);
}
} else {
if (snapSizeX(toolbar.getWidth()) != previousWidth || needsUpdate) {
((HBox)box).setSpacing(getSpacing());
((HBox)box).setAlignment(getBoxAlignment());
previousWidth = snapSizeX(toolbar.getWidth());
addNodesToToolBar();
} else {
correctOverflow(toolbarLength);
}
}

needsUpdate = false;

double toolbarWidth = w;
Expand Down Expand Up @@ -531,8 +537,6 @@ public CssMetaData<ToolBar,Pos> getCssMetaData() {
}
}



/***************************************************************************
* *
* Private implementation *
Expand Down Expand Up @@ -563,32 +567,14 @@ private void initialize() {
getSkinnable().requestLayout();
}

private void addNodesToToolBar() {
final ToolBar toolbar = getSkinnable();
double length = 0;
if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
length = snapSizeY(toolbar.getHeight()) - snappedTopInset() - snappedBottomInset() + getSpacing();
} else {
length = snapSizeX(toolbar.getWidth()) - snappedLeftInset() - snappedRightInset() + getSpacing();
}

// Is there overflow ?
double x = 0;
boolean hasOverflow = false;
for (Node node : getSkinnable().getItems()) {
if (!node.isManaged()) continue;

if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
x += snapSizeY(node.prefHeight(-1)) + getSpacing();
} else {
x += snapSizeX(node.prefWidth(-1)) + getSpacing();
}
if (x > length) {
hasOverflow = true;
break;
}
private void correctOverflow(double length) {
boolean overflowed = isOverflowed(length);
if (overflowed != overflow) {
organizeOverflow(length, overflow);
}
}

private void organizeOverflow(double length, boolean hasOverflow) {
if (hasOverflow) {
if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
length -= snapSizeY(overflowMenu.prefHeight(-1));
Expand All @@ -599,7 +585,8 @@ private void addNodesToToolBar() {
}

// Determine which node goes to the toolbar and which goes to the overflow.
x = 0;

double x = 0;
overflowMenuItems.clear();
box.getChildren().clear();
for (Node node : getSkinnable().getItems()) {
Expand Down Expand Up @@ -687,7 +674,43 @@ private void addNodesToToolBar() {
overflowMenu.setManaged(overflow);
}

private void addNodesToToolBar() {
final ToolBar toolbar = getSkinnable();
double toolbarLength = getToolbarLength(toolbar);

// Is there overflow ?
boolean hasOverflow = isOverflowed(toolbarLength);

organizeOverflow(toolbarLength, hasOverflow);
}

private double getToolbarLength(ToolBar toolbar) {
double length;
if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
length = snapSizeY(toolbar.getHeight()) - snappedTopInset() - snappedBottomInset() + getSpacing();
} else {
length = snapSizeX(toolbar.getWidth()) - snappedLeftInset() - snappedRightInset() + getSpacing();
}
return length;
}

private boolean isOverflowed(double length) {
double x = 0;
boolean hasOverflow = false;
for (Node node : getSkinnable().getItems()) {
if (!node.isManaged()) continue;
if (getSkinnable().getOrientation() == Orientation.VERTICAL) {
x += snapSizeY(node.prefHeight(-1)) + getSpacing();
} else {
x += snapSizeX(node.prefWidth(-1)) + getSpacing();
}
if (x > length) {
hasOverflow = true;
break;
}
}
return hasOverflow;
}

/***************************************************************************
* *
Expand Down
Expand Up @@ -27,6 +27,10 @@

import javafx.css.CssMetaData;
import static test.com.sun.javafx.scene.control.infrastructure.ControlTestUtils.*;

import javafx.scene.AccessibleAttribute;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import test.com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
import test.com.sun.javafx.pgstub.StubToolkit;
import javafx.scene.control.skin.ToolBarSkin;
Expand Down Expand Up @@ -58,10 +62,17 @@
public class ToolbarTest {
private ToolBar toolBar;//Empty
private ToolBar toolBarWithItems;//Items

private Toolkit tk;
private StackPane root;

private Node node1;
private Node node2;

private static final double TOOLBAR_SIZE = 300.0;
private static final double EXPANDED_CHILDREN_SIZE = 250.0;
private static final double ORIGINAL_CHILDREN_SIZE = 100.0;

@Before public void setup() {
tk = (StubToolkit)Toolkit.getToolkit();//This step is not needed (Just to make sure StubToolkit is loaded into VM)
toolBar = new ToolBar();
Expand Down Expand Up @@ -221,4 +232,74 @@ public class ToolbarTest {
tk.firePulse();
assertTrue(btn5.isFocused());
}

@Test public void overflowShownInHorizontalAfterChildrenReziseTest() {
initializeToolBar();

toolBar.setOrientation(Orientation.HORIZONTAL);

testOverflowVisibility();
}

@Test public void overflowShownInVerticalAfterChildrenReziseTest() {
initializeToolBar();

toolBar.setOrientation(Orientation.VERTICAL);

testOverflowVisibility();
}

private void initializeToolBar() {
root = new StackPane(toolBar);
root.setPrefSize(400, 400);

Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setScene(scene);

toolBar.getItems().addAll(node1, node2);
setFixSize(toolBar, TOOLBAR_SIZE);
}

private void testOverflowVisibility() {
setFixSize(node1, ORIGINAL_CHILDREN_SIZE);
setFixSize(node2, ORIGINAL_CHILDREN_SIZE);

assertOverflowNotShown();

setFixSize(node1, EXPANDED_CHILDREN_SIZE);

assertOverflowShown();

setFixSize(node1, ORIGINAL_CHILDREN_SIZE);

assertOverflowNotShown();
}

private void setFixSize(Node node, double size) {
if (node instanceof Region) {
((Region) node).setMinSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
((Region) node).setMaxSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
((Region) node).setPrefSize(size, size);
} else if (node instanceof Rectangle) {
((Rectangle) node).setHeight(size);
((Rectangle) node).setWidth(size);
}

root.applyCss();
root.autosize();
root.layout();
}

private void assertOverflowNotShown() {
Pane pane = (Pane) toolBar.queryAccessibleAttribute(AccessibleAttribute.OVERFLOW_BUTTON);
assertNotNull(pane);
assertFalse(pane.isVisible());
}

private void assertOverflowShown() {
Pane pane = (Pane) toolBar.queryAccessibleAttribute(AccessibleAttribute.OVERFLOW_BUTTON);
assertNotNull(pane);
assertTrue(pane.isVisible());
}
}