Commit 70df2960 authored by Yuri Blankenstein's avatar Yuri Blankenstein
Browse files

#16 Supporting Java 11 (tested until Java17) for JFreeChart SWT

parent 2ead34f5
Pipeline #4384 failed with stage
in 0 seconds
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.trace4cps.common.jfreechart.ui.internal;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static org.eclipse.trace4cps.common.jfreechart.ui.JFreeChartUIPlugin.PLUGIN_ID;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Stack;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.trace4cps.common.jfreechart.ui.JFreeChartUIPlugin;
/**
* Workaround for <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=377104">Eclipse bug 377104</a> where frame
* activation is not being properly propagated into SWT on Java 7 and higher.
*/
public class SWT_AWT_PATCH_377104 extends WindowAdapter { // ignore checkstyle TypeNameCheck
private static final Method SHELL_SET_ACTIVE_CONTROL_METHOD;
static {
Method setActiveControlMethod = null;
try {
setActiveControlMethod = Shell.class.getDeclaredMethod("setActiveControl", Control.class);
setActiveControlMethod.setAccessible(true);
} catch (NoSuchMethodException | SecurityException e) {
String msg = "Patch for bug 377104 cannot be applied: "
+ "org.eclipse.swt.widgets.Shell#setActiveControl(org.eclipse.swt.widgets.Control) not available or accessible. "
+ "This will result in embedded workbench parts not getting activated.";
IStatus status = new Status(ERROR, PLUGIN_ID, msg, e);
JFreeChartUIPlugin.getDefault().getLog().log(status);
setActiveControlMethod = null;
}
SHELL_SET_ACTIVE_CONTROL_METHOD = setActiveControlMethod;
}
/**
* Creates a new <code>java.awt.Frame</code>. This frame is the root for the AWT components that will be embedded
* within the composite. In order for the embedding to succeed, the composite must have been created with the
* SWT.EMBEDDED style.
* <p>
* This method calls {@link SWT_AWT#new_Frame(Composite)} and applies a workaround for
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=377104">Eclipse bug 377104</a> where frame activation is
* not being properly propagated into SWT on Java 7 and higher. The current Java version is not checked.
* </p>
*
* @param parent the parent <code>Composite</code> of the new <code>java.awt.Frame</code>
* @return a <code>java.awt.Frame</code> to be the parent of the embedded AWT components
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the parent Composite does not have the SWT.EMBEDDED style</li>
* </ul>
* @see SWT_AWT#new_Frame(Composite)
*/
public static Frame new_Frame(Composite parent) {
Frame frame = SWT_AWT.new_Frame(parent);
// This plug-in requires Java8 or higher and versions higher than Java7 suffer from bug 377104
// So, no need to check Java version.
if (SHELL_SET_ACTIVE_CONTROL_METHOD != null) {
frame.addWindowListener(new SWT_AWT_PATCH_377104(parent));
}
return frame;
}
private final Composite embedded;
private SWT_AWT_PATCH_377104(Composite embedded) {
this.embedded = embedded;
}
@Override
public void windowActivated(WindowEvent event) {
if (!embedded.isDisposed()) {
try {
embedded.getDisplay().asyncExec(this::activateEmbedded);
} catch (SWTException e) {
String msg = "Embedded part was not able to set active control on Shell. "
+ "This will result in other workbench parts not getting activated.";
IStatus status = new Status(ERROR, PLUGIN_ID, msg, e);
JFreeChartUIPlugin.getDefault().getLog().log(status);
}
}
}
private void activateEmbedded() {
try {
if (Display.getCurrent().getFocusControl() != embedded) {
return;
}
Stack<Control> stack = new Stack<Control>();
Control current = embedded;
Shell shell = embedded.getShell();
while (current != null && !(current instanceof Shell)) {
stack.push(current.getParent());
current = current.getParent();
}
while (!stack.isEmpty()) {
SHELL_SET_ACTIVE_CONTROL_METHOD.invoke(shell, stack.pop());
}
} catch (SWTException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
String msg = "Embedded part was not able to set active control on Shell. "
+ "This will result in other workbench parts not getting activated.";
IStatus status = new Status(ERROR, PLUGIN_ID, msg, e);
JFreeChartUIPlugin.getDefault().getLog().log(status);
}
}
}
......@@ -20,23 +20,17 @@ import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Stack;
import javax.swing.JApplet;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.trace4cps.common.jfreechart.ui.JFreeChartUIPlugin;
import org.eclipse.trace4cps.common.jfreechart.ui.internal.ChartPanelFactory;
import org.eclipse.trace4cps.common.jfreechart.ui.internal.ChartPanelScrollbarHandler;
import org.eclipse.trace4cps.common.jfreechart.ui.internal.SWT_AWT_PATCH_377104;
import org.eclipse.ui.statushandlers.StatusManager;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
......@@ -57,7 +51,7 @@ public class ChartPanelComposite extends Composite {
public ChartPanelComposite(ChartPanel chartPanel, Composite parent, int style) {
super(parent, SWT.EMBEDDED | style);
Args.nullNotPermitted(chartPanel, "chartPanel");
this.baseFrame = SWT_AWT.new_Frame(this);
this.baseFrame = SWT_AWT_PATCH_377104.new_Frame(this);
this.chartPanel = chartPanel;
this.scrollbarHandler = new ChartPanelScrollbarHandler(this);
......@@ -78,9 +72,6 @@ public class ChartPanelComposite extends Composite {
JApplet chartApplet = new JApplet();
chartApplet.add(chartPanel);
baseFrame.add(chartApplet);
// Workaround eclipse bug #377104
workaround377104(baseFrame, this);
}
@Override
......@@ -147,60 +138,6 @@ public class ChartPanelComposite extends Composite {
super.setMenu(menu);
}
/**
* <p>
* Workaround for Eclipse bug 377104 where frame activation is not being properly propagated into SWT on Java 7.
* </p>
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=377104">
*
* Eclipse Bug 377104</a>
*
* @param frame Swing frame
* @param embedded Composite containing embedded swing components
*/
private static final void workaround377104(final Frame frame, final Composite embedded) {
if (System.getProperty("java.version").startsWith("1.7")
|| System.getProperty("java.version").startsWith("1.8"))
{
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowActivated(java.awt.event.WindowEvent e) {
embedded.getDisplay().asyncExec(() -> {
if (Display.getCurrent().getFocusControl() == embedded) {
Stack<Control> stack = new Stack<Control>();
Control starter = embedded;
Shell shell = embedded.getShell();
while (starter != null && !(starter instanceof Shell)) {
stack.push(starter.getParent());
starter = starter.getParent();
}
Method m = null;
try {
m = shell.getClass().getDeclaredMethod("setActiveControl", Control.class);
m.setAccessible(true);
while (!stack.isEmpty()) {
m.invoke(shell, stack.pop());
}
} catch (NoSuchMethodException | SecurityException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e1)
{
String msg = "Embedded part was not able to set active control on Shell. "
+ "This will result in other workbench parts not getting activated.";
IStatus status = new Status(ERROR, PLUGIN_ID, msg, e1);
JFreeChartUIPlugin.getDefault().getLog().log(status);
} finally {
if (m != null) {
m.setAccessible(false);
}
}
}
});
}
});
}
}
private static java.awt.Color toAwtColor(org.eclipse.swt.graphics.Color color) {
return new java.awt.Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
}
......
......@@ -432,7 +432,7 @@ public class TracePlotManager implements XYToolTipGenerator, XYItemLabelGenerato
rangeAxis.setAutoRangeAlign(RangeAlign.LOWER);
rangeAxis.setFixedAutoRange(30);
} else {
rangeAxis.setRange(new Range(0d, rangeAxis.getSections().size())); // all sections visible
rangeAxis.setAutoRange(true);
}
if (!firstPlot) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment