Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pazderski2020-05-01 22:38:01 +0000
committerPaul Pazderski2020-05-07 20:29:56 +0000
commit984bc060c83d55b3781435a1a966fafadd029ab2 (patch)
tree420c14fe10d161d6fbfeeb134ae6bac44fd3d35f
parent6ea564799a0ab24cce1db9b46541acaff0727774 (diff)
downloadeclipse.platform.swt-984bc060c83d55b3781435a1a966fafadd029ab2.tar.gz
eclipse.platform.swt-984bc060c83d55b3781435a1a966fafadd029ab2.tar.xz
eclipse.platform.swt-984bc060c83d55b3781435a1a966fafadd029ab2.zip
Bug 499215 - Chevron is wrapped to new line
The failure can also appear when min or max button is added to a visible CTabFolder. Precondition for this failure is that all CTabItems are smaller in height than the icon + margins. When the min/max is to be shown the following happened before this change: - tab bar height is recalculated - min/max button is created and bounds calculated (at once) The fix for that scenario is to split the one button handling method into a button creation and bounds calculation method and reorder the invocation to: create button, updateTabHeight (which now consider the created buttons) and set button bounds. Situation for chevron is a bit more complicate because the decision if a chevron is shown depends on the item size calculation which already require the tab bar height. The fix is similar to the previous. If chevron is added/removed the tab bar height has to be recalculated for the case it changed from the changed chevron. Change-Id: I1fffac97333c4414ca0dc1394ea87377f12e74fb Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java32
-rw-r--r--tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java101
2 files changed, 122 insertions, 11 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
index 7ee1a40016..86fac25b9f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
@@ -784,9 +784,8 @@ void destroyItem (CTabItem item) {
control.setVisible(false);
}
setToolTipText(null);
- GC gc = new GC(this);
- setButtonBounds(gc);
- gc.dispose();
+ updateButtons();
+ setButtonBounds();
redraw();
return;
}
@@ -2497,8 +2496,11 @@ public void setBorderVisible(boolean show) {
this.borderVisible = show;
updateFolder(REDRAW);
}
-void setButtonBounds(GC gc) {
- Point size = getSize();
+
+/**
+ * Create or dispose min/max buttons.
+ */
+void updateButtons() {
// max button
Display display = getDisplay();
if (showMax) {
@@ -2551,10 +2553,17 @@ void setButtonBounds(GC gc) {
minMaxTb.dispose();
minMaxTb = null;
}
+}
+
+/**
+ * Update button bounds for min/max and update chevron button.
+ */
+void setButtonBounds() {
if (showChevron) {
updateChevronImage(false);
}
+ Point size = getSize();
boolean[][] overflow = new boolean[1][0];
Rectangle[] rects = computeControlBounds(size, overflow);
if (fixedTabHeight != SWT.DEFAULT) {
@@ -3826,9 +3835,17 @@ boolean updateItems (int showIndex) {
boolean oldShowChevron = showChevron;
boolean changed = setItemSize(gc);
+ updateButtons();
+ boolean chevronChanged = showChevron != oldShowChevron;
+ if (chevronChanged) {
+ if (updateTabHeight(false)) {
+ // Tab height has changed. Item sizes have to be set again.
+ changed |= setItemSize(gc);
+ }
+ }
changed |= setItemLocation(gc);
- setButtonBounds(gc);
- changed |= showChevron != oldShowChevron;
+ setButtonBounds();
+ changed |= chevronChanged;
if (changed && getToolTipText() != null) {
Point pt = getDisplay().getCursorLocation();
pt = toControl(pt);
@@ -3872,6 +3889,7 @@ void runUpdate() {
int flags = updateFlags;
updateFlags = 0;
Rectangle rectBefore = getClientArea();
+ updateButtons();
updateTabHeight(false);
updateItems(selectedIndex);
if ((flags & REDRAW) != 0) {
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java
index eeced27d3c..8f0743c425 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java
@@ -44,6 +44,7 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
@@ -122,8 +123,12 @@ private void makeCleanEnvironment(int style) {
}
private void createTabFolder(List<String> events) {
+ createTabFolder(events, 3);
+}
+
+private void createTabFolder(List<String> events, int numItems) {
makeCleanEnvironment();
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < numItems; i++) {
CTabItem item = new CTabItem(ctabFolder, SWT.NONE);
item.setText("CTabItem &" + i);
item.setToolTipText("CTabItem ToolTip" + i);
@@ -285,6 +290,7 @@ public void test_chevronAppearanceChanged() {
ToolItem chevron = showChevron();
Image oldChevronImg = new Image(display, chevron.getImage(), SWT.IMAGE_COPY);
+ Font newFont = null;
try {
ctabFolder.setForeground(display.getSystemColor(SWT.COLOR_DARK_GREEN));
Image newChevronImg = chevron.getImage();
@@ -296,12 +302,15 @@ public void test_chevronAppearanceChanged() {
FontData[] existingFontData = ctabFolder.getFont().getFontData();
existingFontData[0].setName(SwtTestUtil.testFontName);
existingFontData[0].setStyle(SWT.BOLD | SWT.ITALIC);
- Font newFont = new Font(display, existingFontData);
+ newFont = new Font(display, existingFontData);
ctabFolder.setFont(newFont);
newChevronImg = chevron.getImage();
ImageTestUtil.assertImagesNotEqual(oldChevronImg.getImageData(), newChevronImg.getImageData());
} finally {
oldChevronImg.dispose();
+ if (newFont != null) {
+ newFont.dispose();
+ }
}
}
@@ -381,6 +390,37 @@ public void test_childControlOverlap() {
setTopRightAndCheckOverlap.accept(null, 0);
}
+/**
+ * Min/max and chevron icon can appear below tab row.
+ * Test for bug 499215, 533582.
+ */
+@Test
+public void test_iconWrappedOnNextLine() {
+ createTabFolder(null);
+
+ FontData[] existingFontData = ctabFolder.getFont().getFontData();
+ existingFontData[0].setName(SwtTestUtil.testFontName);
+ existingFontData[0].setHeight(3);
+ Font smallFont = new Font(ctabFolder.getDisplay(), existingFontData);
+ try {
+ SwtTestUtil.openShell(shell);
+ ctabFolder.setFont(smallFont);
+
+ ctabFolder.setMaximizeVisible(true);
+ processEvents();
+ assertTabElementsInLine();
+
+ createTabFolder(null, 20);
+ ctabFolder.setFont(smallFont);
+ shell.layout(true, true);
+ showChevron();
+ processEvents();
+ assertTabElementsInLine();
+ } finally {
+ smallFont.dispose();
+ }
+}
+
private void processEvents() {
Display display = shell.getDisplay();
@@ -422,9 +462,13 @@ private ToolItem showChevron() {
itemWidth += item.getBounds().width;
}
// resize shell to force a chevron
- shell.setSize(itemWidth*3/4, shell.getSize().y);
+ int newWidth = itemWidth*3/4;
+ shell.setSize(newWidth, shell.getSize().y);
+ boolean resizeFailed = Math.abs(newWidth - shell.getSize().x) > 10;
ToolItem chevron = getChevron(ctabFolder);
- assertNotNull("Chevron not shown", chevron);
+ assertNotNull("Chevron not shown" + (resizeFailed
+ ? ". Shell could not be resized to the desired size. Tab row width might be smaller than the minimum shell width."
+ : ""), chevron);
return chevron;
}
@@ -498,4 +542,53 @@ private static Control[] reflection_getChildControls(CTabFolder tabFolder) {
}
}
+/**
+ * Check if all CTabItems and toolbar icons like min/max, chevron are all in one line and not wrapped.
+ */
+private void assertTabElementsInLine() {
+ List<Rectangle> tabBarElementBounds = new ArrayList<>();
+ Arrays.stream(ctabFolder.getItems()).filter(CTabItem::isShowing).map(this::getBoundsInShell).forEach(tabBarElementBounds::add);
+ for (Control child : ctabFolder.getChildren()) {
+ if (child instanceof ToolBar) {
+ for (ToolItem toolItem : ((ToolBar)child).getItems()) {
+ if (toolItem.getImage() != null) {
+ tabBarElementBounds.add(getBoundsInShell(toolItem));
+ }
+ }
+ }
+ }
+ Rectangle maxBound = tabBarElementBounds.get(0);
+ for (Rectangle bound : tabBarElementBounds) {
+ if (bound.height > maxBound.height) {
+ assertTrue("Element at " + maxBound + " is not on line.", bound.y <= maxBound.y && bound.y + bound.height >= maxBound.y + maxBound.height);
+ maxBound = bound;
+ } else {
+ assertTrue("Element at " + bound + " is not on line.", bound.y >= maxBound.y && bound.y + bound.height <= maxBound.y + maxBound.height);
+ }
+ }
+}
+
+private Rectangle getBoundsInShell(Widget control) {
+ Control parent;
+ Rectangle bounds;
+ if (control instanceof Control) {
+ parent = ((Control)control).getParent();
+ bounds = ((Control)control).getBounds();
+ } else if (control instanceof CTabItem) {
+ parent = ((CTabItem)control).getParent();
+ bounds = ((CTabItem)control).getBounds();
+ } else if (control instanceof ToolItem) {
+ parent = ((ToolItem)control).getParent();
+ bounds = ((ToolItem)control).getBounds();
+ } else {
+ throw new UnsupportedOperationException("Widget must provide bounds and parent");
+ }
+ if (parent != null && !(parent instanceof Shell)) {
+ Rectangle absParentBound = getBoundsInShell(parent);
+ bounds.x += absParentBound.x;
+ bounds.y += absParentBound.y;
+ }
+ return bounds;
+}
+
}

Back to the top