Skip to content

Commit 8808054

Browse files
committed
Move processing of Swing border to AWT event dispatcher thread
This is a continuation of 979a129, where the Swing border is now consumed in the AWT event dispatcher thread, rather than the SWT UI thread. Interactions between those threads are done asynchronously, to avoid accidental deadlocks.
1 parent e6be725 commit 8808054

16 files changed

+237
-173
lines changed

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderDialog.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.apache.commons.lang3.StringUtils;
5959

6060
import java.util.ArrayList;
61+
import java.util.concurrent.CompletableFuture;
6162

6263
import javax.swing.border.Border;
6364

@@ -224,29 +225,26 @@ protected void okPressed() {
224225
* Updates GUI using current {@link Border}.
225226
*/
226227
private void updateGUI() {
227-
// select page
228-
{
228+
SwingUtils.runLogLater(() -> {
229+
// select page
229230
m_pagesLayout.topControl = m_pages.get(0);
230-
ExecutionUtils.runLog(new RunnableEx() {
231-
@Override
232-
public void run() throws Exception {
233-
for (AbstractBorderComposite page : m_pages) {
234-
// TODO BorderValue
235-
boolean understands = page.setBorder(m_borderValue.doGetValue());
236-
if (understands && m_borderModified) {
237-
m_pagesLayout.topControl = page;
238-
}
239-
}
231+
for (AbstractBorderComposite page : m_pages) {
232+
CompletableFuture<?> understands = page.setBorderValue(m_borderValue);
233+
if (understands != null && m_borderModified) {
234+
m_pagesLayout.topControl = page;
240235
}
236+
}
237+
// update combo
238+
ExecutionUtils.runLogLater(() -> {
239+
m_pagesComposite.layout();
240+
// select in "type" combo
241+
m_typeCombo.select(m_pages.indexOf(m_pagesLayout.topControl));
241242
});
242-
m_pagesComposite.layout();
243-
// select in "type" combo
244-
m_typeCombo.select(m_pages.indexOf(m_pagesLayout.topControl));
245-
}
246-
// update preview
247-
if (m_previewCanvas != null) {
248-
SwingUtils.runLogLater(() -> m_previewCanvas.setBorder(m_borderValue));
249-
}
243+
// update preview
244+
if (m_previewCanvas != null) {
245+
m_previewCanvas.setBorder(m_borderValue);
246+
}
247+
});
250248
}
251249

252250
////////////////////////////////////////////////////////////////////////////

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderValue.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ public Class<?> getValueType() {
6060
}
6161

6262
@Override
63-
public Border doGetValue() {
64-
// TODO Make protected
63+
protected Border doGetValue() {
6564
return border;
6665
}
6766

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/fields/AbstractBorderField.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2011 Google, Inc.
2+
* Copyright (c) 2011, 2025 Google, Inc. and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License 2.0 which is available at
@@ -53,5 +53,5 @@ public AbstractBorderField(Composite parent, int columns, String labelText) {
5353
/**
5454
* @return the source corresponding to the made selection.
5555
*/
56-
public abstract String getSource() throws Exception;
56+
public abstract String getSource();
5757
}

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/fields/BorderField.java

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderDialog;
1818
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderValue;
1919
import org.eclipse.wb.internal.swing.model.property.editor.border.pages.AbstractBorderComposite;
20+
import org.eclipse.wb.internal.swing.utils.SwingUtils;
2021

2122
import org.eclipse.core.runtime.Assert;
2223
import org.eclipse.jface.window.Window;
@@ -28,9 +29,7 @@
2829
import org.eclipse.swt.widgets.Shell;
2930
import org.eclipse.swt.widgets.Text;
3031

31-
import java.util.Iterator;
32-
import java.util.LinkedList;
33-
import java.util.List;
32+
import java.util.concurrent.CompletableFuture;
3433

3534
import javax.swing.border.Border;
3635

@@ -103,7 +102,7 @@ public BorderValue getBorderValue() {
103102
public void setBorderValue(BorderValue borderValue) throws Exception {
104103
Assert.isNotNull(borderValue, "Border value must not be null.");
105104
m_borderValue = borderValue;
106-
m_source = calculateSource();
105+
calculateSource();
107106
showBorder();
108107
}
109108

@@ -112,25 +111,25 @@ public String getSource() {
112111
return m_source;
113112
}
114113

115-
private String calculateSource() throws Exception{
114+
private void calculateSource() throws Exception {
116115
// try to use AbstractBorderComposite's to convert Border into source
117-
// TODO BorderValue
118-
Border border = m_borderValue.doGetValue();
119-
if (border != null) {
120-
Class<?> compositeClass = AbstractBorderComposite.getCompositeClass(border.getClass());
121-
if (compositeClass != null) {
122-
AbstractBorderComposite borderComposite = getBorderComposite(compositeClass);
123-
try {
124-
if (borderComposite.setBorder(border)) {
125-
return borderComposite.getSource();
126-
}
127-
} finally {
128-
returnBorderComposite(borderComposite);
116+
Class<?> compositeClass = AbstractBorderComposite.getCompositeClass(m_borderValue.getValueType());
117+
if (compositeClass != null) {
118+
AbstractBorderComposite borderComposite = getBorderComposite(compositeClass);
119+
SwingUtils.runLogLater(() -> {
120+
CompletableFuture<Void> understands = borderComposite.setBorderValue(m_borderValue);
121+
if (understands != null) {
122+
understands.thenRunAsync(() -> {
123+
m_source = borderComposite.getSource();
124+
borderComposite.dispose();
125+
}, getDisplay()::asyncExec);
126+
} else {
127+
// no, we don't understand this Border return null;
128+
m_source = null;
129+
getDisplay().asyncExec(borderComposite::dispose);
129130
}
130-
}
131+
});
131132
}
132-
// no, we don't understand this Border
133-
return null;
134133
}
135134

136135
@Override
@@ -143,35 +142,19 @@ public AbstractBorderComposite getParent() {
143142
// Borders
144143
//
145144
////////////////////////////////////////////////////////////////////////////
146-
private final List<AbstractBorderComposite> m_borderComposites = new LinkedList<>();
147145

148146
/**
149147
* Note, that we can not reuse {@link AbstractBorderComposite}'s, so when we get some
150148
* {@link AbstractBorderComposite}, we should return it back, else new instance will be created.
151149
*
152150
* @return the instance free of {@link AbstractBorderComposite}.
153151
*/
154-
private final AbstractBorderComposite getBorderComposite(Class<?> compositeClass)
155-
throws Exception {
156-
for (Iterator<AbstractBorderComposite> I = m_borderComposites.iterator(); I.hasNext();) {
157-
AbstractBorderComposite borderComposite = I.next();
158-
if (borderComposite.getClass() == compositeClass) {
159-
I.remove();
160-
return borderComposite;
161-
}
162-
}
152+
private final AbstractBorderComposite getBorderComposite(Class<?> compositeClass) throws Exception {
163153
// create new instance
164154
Shell shell = getParent().getDialog().getTemporaryShell();
165155
return (AbstractBorderComposite) compositeClass.getConstructor(Composite.class).newInstance(shell);
166156
}
167157

168-
/**
169-
* Returns given {@link AbstractBorderComposite} to the list of available.
170-
*/
171-
private final void returnBorderComposite(AbstractBorderComposite borderComposite) {
172-
m_borderComposites.add(borderComposite);
173-
}
174-
175158
////////////////////////////////////////////////////////////////////////////
176159
//
177160
// Internal

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/pages/AbstractBorderComposite.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import org.eclipse.wb.internal.core.utils.ast.AstEditor;
1616
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderDialog;
17+
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderValue;
1718
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.AbstractBorderField;
1819
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.BooleanField;
1920
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.BorderField;
@@ -30,6 +31,7 @@
3031

3132
import java.util.HashMap;
3233
import java.util.Map;
34+
import java.util.concurrent.CompletableFuture;
3335
import java.util.function.Predicate;
3436

3537
import javax.swing.border.Border;
@@ -75,17 +77,17 @@ public final String getTitle() {
7577
}
7678

7779
/**
78-
* Sets the {@link Border} to edit.
80+
* Sets the {@link BorderValue} to edit.
7981
*
80-
* @return <code>true</code> if this {@link AbstractBorderComposite} understands given
81-
* {@link Border}.
82+
* @return A {@link CompletableFuture} if this {@link AbstractBorderComposite}
83+
* understands given {@link BorderValue}, otherwise {@code null}.
8284
*/
83-
public abstract boolean setBorder(Border border) throws Exception;
85+
public abstract CompletableFuture<Void> setBorderValue(BorderValue borderValue);
8486

8587
/**
8688
* @return the source for updated {@link Border}.
8789
*/
88-
public abstract String getSource() throws Exception;
90+
public abstract String getSource();
8991

9092
/**
9193
* Used by the {@link BorderField} for the source code generation.

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/pages/BevelBorderComposite.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
import org.eclipse.wb.internal.core.utils.execution.ExecutionUtils;
1616
import org.eclipse.wb.internal.core.utils.ui.GridLayoutFactory;
1717
import org.eclipse.wb.internal.swing.model.ModelMessages;
18+
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderValue;
1819
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.ColorField;
1920
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.RadioField;
2021

22+
import org.eclipse.core.runtime.Assert;
2123
import org.eclipse.swt.widgets.Composite;
2224

25+
import java.awt.Color;
26+
import java.util.concurrent.CompletableFuture;
27+
28+
import javax.swing.SwingUtilities;
2329
import javax.swing.border.BevelBorder;
24-
import javax.swing.border.Border;
2530

2631
/**
2732
* Implementation of {@link AbstractBorderComposite} that sets {@link BevelBorder}.
@@ -72,19 +77,25 @@ public BevelBorderComposite(Composite parent) {
7277
//
7378
////////////////////////////////////////////////////////////////////////////
7479
@Override
75-
public boolean setBorder(Border border) throws Exception {
76-
if (border instanceof BevelBorder ourBorder) {
77-
m_typeField.setValue(ourBorder.getBevelType());
78-
m_highlightOuterField.setValue(ourBorder.getHighlightOuterColor());
79-
m_highlightInnerField.setValue(ourBorder.getHighlightInnerColor());
80-
m_shadowOuterField.setValue(ourBorder.getShadowOuterColor());
81-
m_shadowInnerField.setValue(ourBorder.getShadowInnerColor());
80+
public CompletableFuture<Void> setBorderValue(BorderValue borderValue) {
81+
Assert.isTrue(SwingUtilities.isEventDispatchThread(), "Must be called from the AWT event dispatcher thread");
82+
if (borderValue.getValue() instanceof BevelBorder ourBorder) {
83+
int bevelType = ourBorder.getBevelType();
84+
Color highlightOuterColor = ourBorder.getHighlightOuterColor();
85+
Color highlightInnerColor = ourBorder.getHighlightInnerColor();
86+
Color shadowOuterColor = ourBorder.getShadowOuterColor();
87+
Color shadowInnerColor = ourBorder.getShadowInnerColor();
8288
// OK, this is our Border
83-
return true;
84-
} else {
85-
// no, we don't know this Border
86-
return false;
89+
return ExecutionUtils.runLogLater(() -> {
90+
m_typeField.setValue(bevelType);
91+
m_highlightOuterField.setValue(highlightOuterColor);
92+
m_highlightInnerField.setValue(highlightInnerColor);
93+
m_shadowOuterField.setValue(shadowOuterColor);
94+
m_shadowInnerField.setValue(shadowInnerColor);
95+
});
8796
}
97+
// no, we don't know this Border
98+
return null;
8899
}
89100

90101
@Override

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/pages/CompoundBorderComposite.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderValue;
2323
import org.eclipse.wb.internal.swing.model.property.editor.border.fields.BorderField;
2424

25+
import org.eclipse.core.runtime.Assert;
2526
import org.eclipse.swt.SWT;
2627
import org.eclipse.swt.widgets.Button;
2728
import org.eclipse.swt.widgets.Composite;
2829
import org.eclipse.swt.widgets.Event;
2930
import org.eclipse.swt.widgets.Listener;
3031

31-
import javax.swing.border.Border;
32+
import java.util.concurrent.CompletableFuture;
33+
34+
import javax.swing.SwingUtilities;
3235
import javax.swing.border.CompoundBorder;
3336

3437
/**
@@ -96,20 +99,23 @@ public void initialize(BorderDialog borderDialog, AstEditor editor) {
9699
}
97100

98101
@Override
99-
public boolean setBorder(Border border) throws Exception {
100-
if (border instanceof CompoundBorder ourBorder) {
101-
m_outsideField.setBorderValue(new BorderValue(ourBorder.getOutsideBorder()));
102-
m_insideField.setBorderValue(new BorderValue(ourBorder.getInsideBorder()));
102+
public CompletableFuture<Void> setBorderValue(BorderValue borderValue) {
103+
Assert.isTrue(SwingUtilities.isEventDispatchThread(), "Must be called from the AWT event dispatcher thread");
104+
if (borderValue.getValue() instanceof CompoundBorder ourBorder) {
105+
BorderValue outsideBorder = new BorderValue(ourBorder.getOutsideBorder());
106+
BorderValue insideBorder = new BorderValue(ourBorder.getInsideBorder());
103107
// OK, this is our Border
104-
return true;
105-
} else {
106-
// no, we don't know this Border
107-
return false;
108+
return ExecutionUtils.runLogLater(() -> {
109+
m_outsideField.setBorderValue(outsideBorder);
110+
m_insideField.setBorderValue(insideBorder);
111+
});
108112
}
113+
// no, we don't know this Border
114+
return null;
109115
}
110116

111117
@Override
112-
public String getSource() throws Exception {
118+
public String getSource() {
113119
String outsideSource = m_outsideField.getSource();
114120
String insideSource = m_insideField.getSource();
115121
if (outsideSource == null && insideSource == null) {

org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/pages/DefaultBorderComposite.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
*******************************************************************************/
1313
package org.eclipse.wb.internal.swing.model.property.editor.border.pages;
1414

15+
import org.eclipse.wb.internal.swing.model.property.editor.border.BorderValue;
16+
1517
import org.eclipse.swt.widgets.Composite;
1618

19+
import java.util.concurrent.CompletableFuture;
20+
1721
import javax.swing.JComponent;
1822
import javax.swing.border.Border;
1923

@@ -41,8 +45,8 @@ public DefaultBorderComposite(Composite parent) {
4145
//
4246
////////////////////////////////////////////////////////////////////////////
4347
@Override
44-
public boolean setBorder(Border border) throws Exception {
45-
return false;
48+
public CompletableFuture<Void> setBorderValue(BorderValue border) {
49+
return null;
4650
}
4751

4852
@Override

0 commit comments

Comments
 (0)