Skip to content

Commit 663d109

Browse files
akoch-yattafedejeanne
authored andcommitted
[win32] Refactor toolbar refresh logic after DPI change
This commit refactors the callback use for ToolBar and ToolItem after a DPI change in the win32 implementation. It makes use of the scalable ImageList to reuse the existing items in the toolbar and only resets the ImageList with a correctly scaled one. Due to the limitations of the win32 implementation all items must be removed and re-added via the win32-API to make shrinking of toolbars possible. Additionally, the commit removes the now unused callback in ToolItem Contributes to #62 and #131.
1 parent 06f1598 commit 663d109

File tree

4 files changed

+58
-97
lines changed

4 files changed

+58
-97
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ public class OS extends C {
13621362
public static final int TBS_DOWNISLEFT = 0x0400;
13631363
public static final int TBS_HORZ = 0x0;
13641364
public static final int TBS_VERT = 0x2;
1365+
public static final int TB_ADDBUTTONS = 0x444;
13651366
public static final int TB_ADDSTRING = 0x44d;
13661367
public static final int TB_AUTOSIZE = 0x421;
13671368
public static final int TB_BUTTONCOUNT = 0x418;

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/ImageList.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public class ImageList {
2525
int style, refCount;
2626
Image [] images;
2727
private final int zoom;
28-
private int width, height;
29-
private int flags;
28+
private final int width, height;
29+
private final int flags;
3030

3131
private HashMap<Integer, Long> zoomToHandle = new HashMap<>();
3232

@@ -36,8 +36,9 @@ public ImageList (int style, int zoom) {
3636

3737
public ImageList (int style, int width, int height, int zoom) {
3838
this.style = style;
39-
this.flags = OS.ILC_MASK | OS.ILC_COLOR32;
40-
if ((style & SWT.RIGHT_TO_LEFT) != 0) this.flags |= OS.ILC_MIRROR;
39+
int listFlags = OS.ILC_MASK | OS.ILC_COLOR32;
40+
if ((style & SWT.RIGHT_TO_LEFT) != 0) listFlags |= OS.ILC_MIRROR;
41+
this.flags = listFlags;
4142
this.height = height;
4243
this.width = width;
4344
handle = OS.ImageList_Create (width, height, this.flags, 16, 16);

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolBar.java

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,10 +1046,11 @@ void setDropDownItems (boolean set) {
10461046
}
10471047

10481048
void setDisabledImageList (ImageList imageList) {
1049-
long hImageList = OS.SendMessage (handle, OS.TB_GETDISABLEDIMAGELIST, 0, 0);
1049+
long hImageList = 0;
10501050
if ((disabledImageList = imageList) != null) {
1051+
hImageList = OS.SendMessage(handle, OS.TB_GETDISABLEDIMAGELIST, 0, 0);
10511052
long newImageList = disabledImageList.getHandle(getZoom());
1052-
if(hImageList == newImageList) return;
1053+
if (hImageList == newImageList) return;
10531054
hImageList = newImageList;
10541055
}
10551056
setDropDownItems (false);
@@ -1084,10 +1085,11 @@ public void setFont (Font font) {
10841085
}
10851086

10861087
void setHotImageList (ImageList imageList) {
1087-
long hImageList = OS.SendMessage (handle, OS.TB_GETHOTIMAGELIST, 0, 0);
1088+
long hImageList = 0;
10881089
if ((hotImageList = imageList) != null) {
1090+
hImageList = OS.SendMessage(handle, OS.TB_GETHOTIMAGELIST, 0, 0);
10891091
long newImageList = hotImageList.getHandle(getZoom());
1090-
if(hImageList == newImageList) return;
1092+
if (hImageList == newImageList) return;
10911093
hImageList = newImageList;
10921094
}
10931095
setDropDownItems (false);
@@ -1096,8 +1098,9 @@ void setHotImageList (ImageList imageList) {
10961098
}
10971099

10981100
void setImageList (ImageList imageList) {
1099-
long hImageList = OS.SendMessage (handle, OS.TB_GETIMAGELIST, 0, 0);
1101+
long hImageList = 0;
11001102
if ((this.imageList = imageList) != null) {
1103+
hImageList = OS.SendMessage(handle, OS.TB_GETIMAGELIST, 0, 0);
11011104
long newImageList = imageList.getHandle(getZoom());
11021105
if (hImageList == newImageList) return;
11031106
hImageList = newImageList;
@@ -1745,75 +1748,59 @@ private static void handleDPIChange(Widget widget, int newZoom, float scalingFac
17451748
if (!(widget instanceof ToolBar toolBar)) {
17461749
return;
17471750
}
1748-
ToolItem[] toolItems = toolBar._getItems ();
1749-
// Only Items with SWT.Sepreator Style have an own width assigned to them
1750-
var seperatorWidth = new int[toolItems.length];
1751-
var enabledState = new boolean[toolItems.length];
1752-
var selectedState = new boolean[toolItems.length];
1753-
for (int i = 0; i < toolItems.length; i++) {
1751+
ToolItem[] toolItems = toolBar._getItems();
1752+
var seperatorWidth = new int[toolItems.length];
1753+
int itemCount = toolItems.length;
1754+
1755+
// Remove and re-add all button the let Windows resize the tool bar
1756+
ToolItem[] items = new ToolItem[itemCount];
1757+
TBBUTTON[] buttondata = new TBBUTTON[itemCount];
1758+
for (int i = itemCount - 1; i >= 0; i--) {
17541759
ToolItem item = toolItems[i];
1755-
if((item.style & SWT.SEPARATOR) != 0) {
1756-
// Take note of widths, so we can re-apply them later
1760+
if ((item.style & SWT.SEPARATOR) != 0 && item.getControl() != null) {
1761+
// Take note of widths of separators with control, so they can be resized
1762+
// at the end
17571763
seperatorWidth[i] = item.getWidth();
17581764
}
1759-
// Remember states of ToolItem to apply them later
1760-
enabledState[i] = item.getEnabled();
1761-
selectedState[i] = item.getSelection();
1762-
1763-
}
1764-
for (ToolItem item : toolItems) {
1765-
// toolBar.destroyItem(item);
1766-
// Resize after, as zoom update changes references to imageLists
17671765
DPIZoomChangeRegistry.applyChange(item, newZoom, scalingFactor);
1768-
}
1769-
1770-
for (int i = 0; i < toolItems.length; i++) {
1771-
ToolItem toolItem = toolItems[i];
1772-
1773-
// toolBar.createItem(toolItem, i);
1774-
String currentText = toolItem.getText();
1775-
toolItem.setText(" ");
1776-
toolItem.setText(currentText);
1777-
1778-
// Refresh images (upscaling already performed by toolItem)
1779-
Image image = toolItem.getImage();
1780-
toolItem.setImage(null);
1781-
toolItem.setImage(image);
17821766

1783-
Image hotImage = toolItem.getHotImage();
1784-
toolItem.setHotImage(null);
1785-
toolItem.setHotImage(hotImage);
1786-
1787-
Image disabledImage = toolItem.getDisabledImage();
1788-
toolItem.setDisabledImage(null);
1789-
toolItem.setDisabledImage(disabledImage);
1790-
1791-
var content = toolItem.getControl();
1792-
toolItem.setControl(null);
1793-
toolItem.setControl(content);
1794-
1795-
// In SWT, Width can only be set for Separators
1796-
if ((toolItem.style & SWT.SEPARATOR) != 0) {
1797-
var width = (int)((seperatorWidth[i]) * scalingFactor);
1798-
toolItem.setWidth(width);
1799-
toolItem.resizeControl();
1767+
TBBUTTON lpButton = new TBBUTTON ();
1768+
OS.SendMessage (toolBar.handle, OS.TB_GETBUTTON, i, lpButton);
1769+
buttondata[lpButton.idCommand] = lpButton;
1770+
items[lpButton.idCommand] = item;
1771+
OS.SendMessage(toolBar.handle, OS.TB_DELETEBUTTON, i, 0);
1772+
}
1773+
1774+
// Refresh the image lists so the image list for the correct zoom is used
1775+
toolBar.setImageList(toolBar.getImageList());
1776+
toolBar.setDisabledImageList(toolBar.getDisabledImageList());
1777+
toolBar.setHotImageList(toolBar.getHotImageList());
1778+
1779+
OS.SendMessage(toolBar.handle, OS.TB_BUTTONSTRUCTSIZE, TBBUTTON.sizeof, 0);
1780+
for (int i = 0; i < buttondata.length; i++) {
1781+
TBBUTTON button = buttondata[i];
1782+
if (button != null) {
1783+
OS.SendMessage(toolBar.handle, OS.TB_ADDBUTTONS, 1, button);
1784+
ToolItem item = items[i];
1785+
1786+
// The text is not retained correctly, so we need to reset it
1787+
String text = item.getText();
1788+
if (text != null) {
1789+
item.setText("");
1790+
item.setText(text);
1791+
}
18001792
}
1801-
1802-
toolItem.setEnabled(enabledState[i]);
1803-
toolItem.setSelection(selectedState[i]);
18041793
}
1794+
OS.SendMessage(toolBar.handle, OS.TB_AUTOSIZE, 0, 0);
18051795

1806-
// Force a refresh of the toolbar by resetting the Font
1807-
toolBar.setDropDownItems(false);
1808-
long hFont = OS.SendMessage(toolBar.handle, OS.WM_GETFONT, 0, 0);
1809-
OS.SendMessage(toolBar.handle, OS.WM_SETFONT, hFont, 0);
1810-
if((toolBar.style & SWT.VERTICAL) != 0) {
1811-
// Reset row count to prevent wrapping of buttons
1812-
toolBar.setRowCount((int)OS.SendMessage (toolBar.handle, OS.TB_BUTTONCOUNT, 0, 0));
1796+
for (int i = 0; i < itemCount; i++) {
1797+
ToolItem item = toolItems[i];
1798+
// If the separator is used with a control, we must reset the size to the cached value,
1799+
// cause windows will treat the separator as normal separator and shrinks it accordingly
1800+
if ((item.style & SWT.SEPARATOR) != 0 && item.getControl() != null) {
1801+
item.setWidth(seperatorWidth[i]);
1802+
}
18131803
}
1814-
toolBar.setDropDownItems(true);
18151804
toolBar.layout(true);
1816-
toolBar.sendResize();
1817-
toolBar.redraw();
18181805
}
18191806
}

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ public class ToolItem extends Item {
5050
short cx;
5151
int foreground = -1, background = -1;
5252

53-
static {
54-
DPIZoomChangeRegistry.registerHandler(ToolItem::handleDPIChange, ToolItem.class);
55-
}
56-
5753
/**
5854
* Constructs a new instance of this class given its parent
5955
* (which must be a <code>ToolBar</code>) and a style value
@@ -1218,28 +1214,4 @@ LRESULT wmCommandChild (long wParam, long lParam) {
12181214
sendSelectionEvent (SWT.Selection);
12191215
return null;
12201216
}
1221-
1222-
private static void handleDPIChange(Widget widget, int newZoom, float scalingFactor) {
1223-
if (!(widget instanceof ToolItem item)) {
1224-
return;
1225-
}
1226-
Image image = item.getImage();
1227-
if (image != null) {
1228-
ToolBar parent = item.getParent();
1229-
Display display = item.getDisplay();
1230-
int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
1231-
1232-
Rectangle bounds = DPIUtil.scaleBounds(image.getBounds(), newZoom, 100);
1233-
if (parent.getImageList() == null) {
1234-
parent.setImageList (display.getImageListToolBar (listStyle, bounds.width, bounds.height, item.getZoom()));
1235-
}
1236-
if (parent.getDisabledImageList() == null) {
1237-
parent.setDisabledImageList (display.getImageListToolBarDisabled (listStyle, bounds.width, bounds.height, item.getZoom()));
1238-
}
1239-
if (parent.getHotImageList() == null) {
1240-
parent.setHotImageList (display.getImageListToolBarHot (listStyle, bounds.width, bounds.height, item.getZoom()));
1241-
}
1242-
}
1243-
item.setWidthInPixels(0);
1244-
}
12451217
}

0 commit comments

Comments
 (0)