diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/AnimatedProgress.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/AnimatedProgress.java index 0f3196c0cf5..f113438bc9b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/AnimatedProgress.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/AnimatedProgress.java @@ -195,9 +195,7 @@ public synchronized void start() { final Runnable [] timer = new Runnable [1]; timer [0] = () -> { if (!active) return; - GC gc = new GC(AnimatedProgress.this); - paintStripes(gc); - gc.dispose(); + GC.drawOn(AnimatedProgress.this, gc -> paintStripes(gc)); display.timerExec (SLEEP, timer [0]); }; display.timerExec (SLEEP, timer [0]); diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java index 0dbe029f637..e4d45739b9b 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java @@ -270,16 +270,16 @@ private Point getTotalSize(Image image, String text) { size.y += r.height; } - GC gc = new GC(this); - if (text != null && text.length() > 0) { - Point e = gc.textExtent(text, DRAW_FLAGS); - size.x += e.x; - size.y = Math.max(size.y, e.y); - if (image != null) size.x += GAP; - } else { - size.y = Math.max(size.y, gc.getFontMetrics().getHeight()); - } - gc.dispose(); + GC.drawOn(this, gc -> { + if (text != null && text.length() > 0) { + Point e = gc.textExtent(text, DRAW_FLAGS); + size.x += e.x; + size.y = Math.max(size.y, e.y); + if (image != null) size.x += GAP; + } else { + size.y = Math.max(size.y, gc.getFontMetrics().getHeight()); + } + }); return size; } 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 d1acaab705a..8650c6ebe05 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 @@ -3835,42 +3835,25 @@ boolean updateItems() { } boolean updateItems (int showIndex) { - GC gc = new GC(this); - if (!single && !mru && showIndex != -1) { - // make sure selected item will be showing - int firstIndex = showIndex; - if (priority[0] < showIndex) { - int maxWidth = getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER); - int width = 0; - int[] widths = new int[items.length]; - for (int i = priority[0]; i <= showIndex; i++) { - int state = CTabFolderRenderer.MINIMUM_SIZE; - if (i == selectedIndex) state |= SWT.SELECTED; - widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; - width += widths[i]; - if (width > maxWidth) break; - } - if (width > maxWidth) { - width = 0; - for (int i = showIndex; i >= 0; i--) { - int state = CTabFolderRenderer.MINIMUM_SIZE; - if (i == selectedIndex) state |= SWT.SELECTED; - if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; - width += widths[i]; - if (width > maxWidth) break; - firstIndex = i; - } - } else { - firstIndex = priority[0]; - for (int i = showIndex + 1; i < items.length; i++) { + final boolean changed[] = new boolean[] {false}; + GC.drawOn(this, gc -> { + if (!single && !mru && showIndex != -1) { + // make sure selected item will be showing + int firstIndex = showIndex; + if (priority[0] < showIndex) { + int maxWidth = getRightItemEdge(gc) - getLeftItemEdge(gc, CTabFolderRenderer.PART_BORDER); + int width = 0; + int[] widths = new int[items.length]; + for (int i = priority[0]; i <= showIndex; i++) { int state = CTabFolderRenderer.MINIMUM_SIZE; if (i == selectedIndex) state |= SWT.SELECTED; widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; width += widths[i]; - if (width >= maxWidth) break; + if (width > maxWidth) break; } - if (width < maxWidth) { - for (int i = priority[0] - 1; i >= 0; i--) { + if (width > maxWidth) { + width = 0; + for (int i = showIndex; i >= 0; i--) { int state = CTabFolderRenderer.MINIMUM_SIZE; if (i == selectedIndex) state |= SWT.SELECTED; if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; @@ -3878,51 +3861,69 @@ boolean updateItems (int showIndex) { if (width > maxWidth) break; firstIndex = i; } + } else { + firstIndex = priority[0]; + for (int i = showIndex + 1; i < items.length; i++) { + int state = CTabFolderRenderer.MINIMUM_SIZE; + if (i == selectedIndex) state |= SWT.SELECTED; + widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; + width += widths[i]; + if (width >= maxWidth) break; + } + if (width < maxWidth) { + for (int i = priority[0] - 1; i >= 0; i--) { + int state = CTabFolderRenderer.MINIMUM_SIZE; + if (i == selectedIndex) state |= SWT.SELECTED; + if (widths[i] == 0) widths[i] = renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; + width += widths[i]; + if (width > maxWidth) break; + firstIndex = i; + } + } } - } - } - if (firstIndex != priority[0]) { - int index = 0; - // enumerate tabs from first visible to the last existing one (sorted ascending) - for (int i = firstIndex; i < items.length; i++) { - priority[index++] = i; } - // enumerate hidden tabs on the left hand from first visible one - // in the inverse order (sorted descending) so that the originally - // first opened tab is always at the end of the list - for (int i = firstIndex - 1; i >= 0; i--) { - priority[index++] = i; + if (firstIndex != priority[0]) { + int index = 0; + // enumerate tabs from first visible to the last existing one (sorted ascending) + for (int i = firstIndex; i < items.length; i++) { + priority[index++] = i; + } + // enumerate hidden tabs on the left hand from first visible one + // in the inverse order (sorted descending) so that the originally + // first opened tab is always at the end of the list + for (int i = firstIndex - 1; i >= 0; i--) { + priority[index++] = i; + } } } - } - 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); + boolean oldShowChevron = showChevron; + changed[0] = setItemSize(gc); + updateButtons(); + boolean chevronChanged = showChevron != oldShowChevron; + if (chevronChanged) { + if (updateTabHeight(false)) { + // Tab height has changed. Item sizes have to be set again. + changed[0] |= setItemSize(gc); + } } - } - changed |= setItemLocation(gc); - setButtonBounds(); - changed |= chevronChanged; - if (changed && getToolTipText() != null) { - Point pt = getDisplay().getCursorLocation(); - pt = toControl(pt); - _setToolTipText(pt.x, pt.y); - } - gc.dispose(); - return changed; + changed[0] |= setItemLocation(gc); + setButtonBounds(); + changed[0] |= chevronChanged; + if (changed[0] && getToolTipText() != null) { + Point pt = getDisplay().getCursorLocation(); + pt = toControl(pt); + _setToolTipText(pt.x, pt.y); + } + }); + return changed[0]; } boolean updateTabHeight(boolean force){ int oldHeight = tabHeight; - GC gc = new GC(this); - tabHeight = renderer.computeSize(CTabFolderRenderer.PART_HEADER, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).y; - gc.dispose(); + GC.drawOn(this, gc ->{ + tabHeight = renderer.computeSize(CTabFolderRenderer.PART_HEADER, SWT.NONE, gc, SWT.DEFAULT, SWT.DEFAULT).y; + }); if (fixedTabHeight == SWT.DEFAULT && controls != null && controls.length > 0) { for (int i = 0; i < controls.length; i++) { if ((controlAlignments[i] & SWT.WRAP) == 0 && !controls[i].isDisposed() && controls[i].getVisible()) { @@ -4008,9 +4009,7 @@ void updateBkImages(boolean colorChanged) { bkImageBounds[i] = bounds; if (controlBkImages[i] != null) controlBkImages[i].dispose(); controlBkImages[i] = new Image(control.getDisplay(), bounds); - GC gc = new GC(controlBkImages[i]); - renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc); - gc.dispose(); + GC.drawOn(controlBkImages[i], gc-> renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc)); control.setBackground(null); control.setBackgroundImage(controlBkImages[i]); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java index 465b18c56ee..49643de9d27 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolderLayout.java @@ -29,59 +29,59 @@ protected Point computeSize(Composite composite, int wHint, int hHint, boolean f CTabItem[] items = folder.items; CTabFolderRenderer renderer = folder.renderer; // preferred width of tab area to show all tabs - int tabW = 0; - int selectedIndex = folder.selectedIndex; - if (selectedIndex == -1) selectedIndex = 0; - GC gc = new GC(folder); - for (int i = 0; i < items.length; i++) { - if (folder.single) { - tabW = Math.max(tabW, renderer.computeSize(i, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT).x); - } else { - int state = 0; - if (i == selectedIndex) state |= SWT.SELECTED; - tabW += renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; + final int[] tabW = new int[] {0}; + final int[] selectedIndex = new int[] {folder.selectedIndex}; + if (selectedIndex[0] == -1) selectedIndex[0] = 0; + final int[] wrapHeight = new int[] {0}; + GC.drawOn(folder, gc -> { + for (int i = 0; i < items.length; i++) { + if (folder.single) { + tabW[0] = Math.max(tabW[0], renderer.computeSize(i, SWT.SELECTED, gc, SWT.DEFAULT, SWT.DEFAULT).x); + } else { + int state = 0; + if (i == selectedIndex[0]) state |= SWT.SELECTED; + tabW[0] += renderer.computeSize(i, state, gc, SWT.DEFAULT, SWT.DEFAULT).x; + } } - } - int width = 0, wrapHeight = 0; - boolean leftControl = false, rightControl = false; - if (wHint == SWT.DEFAULT) { - for (int i = 0; i < folder.controls.length; i++) { - Control control = folder.controls[i]; - if (!control.isDisposed() && control.getVisible()) { - if ((folder.controlAlignments[i] & SWT.LEAD) != 0) { - leftControl = true; - } else { - rightControl = true; + int width = 0; + boolean leftControl = false, rightControl = false; + if (wHint == SWT.DEFAULT) { + for (int i = 0; i < folder.controls.length; i++) { + Control control = folder.controls[i]; + if (!control.isDisposed() && control.getVisible()) { + if ((folder.controlAlignments[i] & SWT.LEAD) != 0) { + leftControl = true; + } else { + rightControl = true; + } + width += control.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; } - width += control.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; } - } - } else { - Point size = new Point (wHint, hHint); - boolean[][] positions = new boolean[1][]; - Rectangle[] rects = folder.computeControlBounds(size, positions); - int minY = Integer.MAX_VALUE, maxY = 0; - for (int i = 0; i < rects.length; i++) { - if (positions[0][i]) { - minY = Math.min(minY, rects[i].y); - maxY = Math.max(maxY, rects[i].y + rects[i].height); - wrapHeight = maxY - minY; - } else { - if ((folder.controlAlignments[i] & SWT.LEAD) != 0) { - leftControl = true; + } else { + Point size = new Point (wHint, hHint); + boolean[][] positions = new boolean[1][]; + Rectangle[] rects = folder.computeControlBounds(size, positions); + int minY = Integer.MAX_VALUE, maxY = 0; + for (int i = 0; i < rects.length; i++) { + if (positions[0][i]) { + minY = Math.min(minY, rects[i].y); + maxY = Math.max(maxY, rects[i].y + rects[i].height); + wrapHeight[0] = maxY - minY; } else { - rightControl = true; + if ((folder.controlAlignments[i] & SWT.LEAD) != 0) { + leftControl = true; + } else { + rightControl = true; + } + width += rects[i].width; } - width += rects[i].width; } } - } - if (leftControl) width += CTabFolder.SPACING * 2; - if (rightControl) width += CTabFolder.SPACING * 2; - tabW += width; - - gc.dispose(); + if (leftControl) width += CTabFolder.SPACING * 2; + if (rightControl) width += CTabFolder.SPACING * 2; + tabW[0] += width; + }); int controlW = 0; int controlH = 0; @@ -95,8 +95,8 @@ protected Point computeSize(Composite composite, int wHint, int hHint, boolean f } } - int minWidth = Math.max(tabW, controlW + folder.marginWidth); - int minHeight = (folder.minimized) ? 0 : controlH + wrapHeight; + int minWidth = Math.max(tabW[0], controlW + folder.marginWidth); + int minHeight = (folder.minimized) ? 0 : controlH + wrapHeight[0]; if (minWidth == 0) minWidth = CTabFolder.DEFAULT_WIDTH; if (minHeight == 0) minHeight = CTabFolder.DEFAULT_HEIGHT; diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java index 675cad903a8..e82d3acde65 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextDropTargetEffect.java @@ -161,19 +161,19 @@ public void dragOver(DropTargetEvent event) { pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) { if (System.currentTimeMillis() >= scrollBeginTime) { Rectangle area = text.getClientArea(); - GC gc = new GC(text); - FontMetrics fm = gc.getFontMetrics(); - gc.dispose(); - double charWidth = fm.getAverageCharacterWidth(); - int scrollAmount = (int) (10*charWidth); - if (pt.x < area.x + 3*charWidth) { - int leftPixel = text.getHorizontalPixel(); - text.setHorizontalPixel(leftPixel - scrollAmount); - } - if (pt.x > area.width - 3*charWidth) { - int leftPixel = text.getHorizontalPixel(); - text.setHorizontalPixel(leftPixel + scrollAmount); - } + GC.drawOn(text, gc->{ + FontMetrics fm = gc.getFontMetrics(); + double charWidth = fm.getAverageCharacterWidth(); + int scrollAmount = (int) (10*charWidth); + if (pt.x < area.x + 3*charWidth) { + int leftPixel = text.getHorizontalPixel(); + text.setHorizontalPixel(leftPixel - scrollAmount); + } + if (pt.x > area.width - 3*charWidth) { + int leftPixel = text.getHorizontalPixel(); + text.setHorizontalPixel(leftPixel + scrollAmount); + } + }); int lineHeight = text.getLineHeight(); if (pt.y < area.y + lineHeight) { int topPixel = text.getTopPixel(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index 900554a8bc3..13c01dedc83 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -1500,10 +1500,10 @@ void setFont(Font font, int tabs) { tabWidth = layout.getBounds().width; layout.dispose(); if (styledText != null) { - GC gc = new GC(styledText); - averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth(); - fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$ - gc.dispose(); + GC.drawOn(styledText, gc->{ + averageCharWidth = (int) gc.getFontMetrics().getAverageCharacterWidth(); + fixedPitch = gc.stringExtent("l").x == gc.stringExtent("W").x; //$NON-NLS-1$ //$NON-NLS-2$ + }); } } void setLineAlignment(int startLine, int count, int alignment) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/GCRunnable.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/GCRunnable.java new file mode 100644 index 00000000000..1e2f36fb1d8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/GCRunnable.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2024 Tobias Melcher and others + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Tobias Melcher - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt; + +import org.eclipse.swt.graphics.*; + +/** + * A method that gets a GC as input, returns no result and may throw a checked + * exception of the given type. + * + * @since 3.125 + */ + +@FunctionalInterface +public interface GCRunnable { + void run(GC gc) throws E; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index 073fe63c960..d714cf2cca3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -114,7 +114,8 @@ public final class GC extends Resource { * foreground color, background color and font in the GC * to match those in the drawable. *

- * You must dispose the graphics context when it is no longer required. + * You must dispose the graphics context when it is no longer required + * or better use {@link #drawOn(Drawable, GCRunnable)} which takes care of disposing the GC. *

* @param drawable the drawable to draw on * @exception IllegalArgumentException