From: Mathieu Baudier Date: Thu, 7 Mar 2024 15:23:15 +0000 (+0100) Subject: Working multi RCP platform X-Git-Tag: v2.3.28~23 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=f92ba77466d18fcd0e7a9386ae0f16b530337f9f Working multi RCP platform --- diff --git a/org.argeo.cms.ee/bnd.bnd b/org.argeo.cms.ee/bnd.bnd index f09995c00..adff33d30 100644 --- a/org.argeo.cms.ee/bnd.bnd +++ b/org.argeo.cms.ee/bnd.bnd @@ -3,9 +3,11 @@ org.osgi.service.http;version=0.0.0,\ org.osgi.service.http.whiteboard;version=0.0.0,\ org.osgi.framework.namespace;version=0.0.0,\ org.argeo.cms.osgi,\ -javax.servlet.*;version="[3,5)",\ * +# javax.servlet.*;version="[3,5)",\ + + Service-Component:\ OSGI-INF/pkgServletContext.xml,\ OSGI-INF/pkgServlet.xml,\ diff --git a/org.argeo.cms.jshell/src/org/argeo/internal/cms/jshell/osgi/OsgiExecutionControlProvider.java b/org.argeo.cms.jshell/src/org/argeo/internal/cms/jshell/osgi/OsgiExecutionControlProvider.java index 9ebf97ed0..67515e69c 100644 --- a/org.argeo.cms.jshell/src/org/argeo/internal/cms/jshell/osgi/OsgiExecutionControlProvider.java +++ b/org.argeo.cms.jshell/src/org/argeo/internal/cms/jshell/osgi/OsgiExecutionControlProvider.java @@ -212,7 +212,7 @@ public class OsgiExecutionControlProvider implements ExecutionControlProvider { static Path bundleToPath(Path frameworkLocation, Bundle bundle) throws IOException { String location = bundle.getLocation(); - if (location.startsWith("initial@reference:file:")) { + if (location.startsWith("initial@reference:file:")) {// Eclipse IDE environment location = location.substring("initial@reference:file:".length()); Path p = frameworkLocation.getParent().resolve(location).toAbsolutePath(); if (Files.exists(p)) { @@ -225,6 +225,15 @@ public class OsgiExecutionControlProvider implements ExecutionControlProvider { log.warn("Ignore bundle " + p + " as it does not exist"); return null; } + } else if (location.startsWith("reference:file:")) {// a2+reference + location = location.substring("reference:".length()); + Path p = Paths.get(URI.create(location)); + if (Files.exists(p)) { + return p; + } else { + log.warn("Ignore bundle " + p + " as it does not exist"); + return null; + } } Path p = Paths.get(location); return p; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java index 405fa46f4..5fc6fcb4f 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsOsgiLogger.java @@ -44,7 +44,10 @@ public class CmsOsgiLogger implements LogListener { // @Override public void logged(LogEntry status) { - CmsLog pluginLog = CmsLog.getLog(status.getBundle().getSymbolicName()); + String loggerName = status.getBundle().getSymbolicName(); + if (loggerName == null) + loggerName = "org.argeo.ext.osgi"; + CmsLog pluginLog = CmsLog.getLog(loggerName); LogLevel severity = status.getLogLevel(); if (severity.equals(LogLevel.ERROR) && pluginLog.isErrorEnabled()) { // FIXME Fix Argeo TP diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java index 0d53a09b0..d3f4b575a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java @@ -123,7 +123,7 @@ public class CmsDeploymentImpl implements CmsDeployment { if (contextPath == null) return; // ignore silently httpHandlers.remove(contextPath); - if (!httpServer.isDone()) + if (!httpExpected || !httpServer.isDone()) return; // TODO use resultNow when switching to Java 21 httpServer.join().removeContext(contextPath); diff --git a/org.argeo.init/bnd.bnd b/org.argeo.init/bnd.bnd index 34023cc7d..c207cb8f1 100644 --- a/org.argeo.init/bnd.bnd +++ b/org.argeo.init/bnd.bnd @@ -7,4 +7,6 @@ Import-Package: \ org.osgi.*;version=0.0.0,\ java.util.logging;resolution:=optional -Export-Package: org.argeo.api.* \ No newline at end of file +Export-Package: \ +org.argeo.api.*,\ +org.argeo.init.osgi,\ \ No newline at end of file diff --git a/org.argeo.init/src/org/argeo/api/init/RuntimeManager.java b/org.argeo.init/src/org/argeo/api/init/RuntimeManager.java index 113aa46c4..da15b1ebc 100644 --- a/org.argeo.init/src/org/argeo/api/init/RuntimeManager.java +++ b/org.argeo.init/src/org/argeo/api/init/RuntimeManager.java @@ -1,11 +1,45 @@ package org.argeo.api.init; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; +import java.util.Properties; import java.util.function.Consumer; /** Dynamically manages multiple runtimes within a single JVM. */ public interface RuntimeManager { + String JVM_ARGS = "jvm.args"; + String STATE = "state"; + String DATA = "data"; + public void startRuntime(String relPath, Consumer> configCallback); public void closeRuntime(String relPath, boolean async); + + static void loadConfig(Path dir, Map config) { + try { + // System.out.println("Load from " + dir); + Path jvmArgsPath = dir.resolve(RuntimeManager.JVM_ARGS); + if (!Files.exists(jvmArgsPath)) { + // load from parent directory + loadConfig(dir.getParent(), config); + } + + if (Files.exists(dir)) + for (Path p : Files.newDirectoryStream(dir, "*.ini")) { + Properties props = new Properties(); + try (InputStream in = Files.newInputStream(p)) { + props.load(in); + } + for (Object key : props.keySet()) { + config.put(key.toString(), props.getProperty(key.toString())); + } + } + } catch (IOException e) { + throw new UncheckedIOException("Cannot load configuration from " + dir, e); + } + } } diff --git a/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java b/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java index 5a8331dfe..7a3f78139 100644 --- a/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java +++ b/org.argeo.init/src/org/argeo/init/RuntimeManagerMain.java @@ -2,19 +2,14 @@ package org.argeo.init; import static org.argeo.api.init.InitConstants.SYMBOLIC_NAME_INIT; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; import java.lang.System.Logger; import java.lang.System.Logger.Level; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Map; -import java.util.Properties; import java.util.TreeMap; import java.util.function.Consumer; @@ -43,19 +38,20 @@ public class RuntimeManagerMain implements RuntimeManager { private final static long RUNTIME_SHUTDOWN_TIMEOUT = 60 * 1000; - private final static String JVM_ARGS = "jvm.args"; - private Path baseConfigArea; - private Path baseStateArea; + private Path baseWritableArea; private Map configuration = new HashMap<>(); private Map runtimeContexts = new TreeMap<>(); RuntimeManagerMain(Path configArea, Path stateArea) { - loadConfig(configArea, configuration); - configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString()); + RuntimeManager.loadConfig(configArea, configuration); + configuration.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.resolve(STATE).toUri().toString()); + // use config area if instance area is not set + if (!configuration.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA)) + configuration.put(InitConstants.PROP_OSGI_INSTANCE_AREA, stateArea.resolve(DATA).toUri().toString()); this.baseConfigArea = configArea.getParent(); - this.baseStateArea = stateArea.getParent(); + this.baseWritableArea = stateArea.getParent(); logger.log(Level.TRACE, () -> "Runtime manager configuration: " + configuration); @@ -129,44 +125,20 @@ public class RuntimeManagerMain implements RuntimeManager { } } - public static void loadConfig(Path dir, Map config) { - try { -// System.out.println("Load from " + dir); - Path jvmArgsPath = dir.resolve(JVM_ARGS); - if (!Files.exists(jvmArgsPath)) { - // load from parent directory - loadConfig(dir.getParent(), config); - } - - if (Files.exists(dir)) - for (Path p : Files.newDirectoryStream(dir, "*.ini")) { - Properties props = new Properties(); - try (InputStream in = Files.newInputStream(p)) { - props.load(in); - } - for (Object key : props.keySet()) { - config.put(key.toString(), props.getProperty(key.toString())); - } - } - } catch (IOException e) { - throw new UncheckedIOException("Cannot load configuration from " + dir, e); - } - } - OsgiRuntimeContext loadRuntime(String relPath, Consumer> configCallback) { closeRuntime(relPath, false); - Path stateArea = baseStateArea.resolve(relPath); + Path writableArea = baseWritableArea.resolve(relPath); Path configArea = baseConfigArea.resolve(relPath); Map config = new HashMap<>(); - loadConfig(configArea, config); - config.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, stateArea.toUri().toString()); + RuntimeManager.loadConfig(configArea, config); + config.put(InitConstants.PROP_OSGI_CONFIGURATION_AREA, writableArea.resolve(STATE).toUri().toString()); if (configCallback != null) configCallback.accept(config); // use config area if instance area is not set if (!config.containsKey(InitConstants.PROP_OSGI_INSTANCE_AREA)) - config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, config.get(InitConstants.PROP_OSGI_CONFIGURATION_AREA)); + config.put(InitConstants.PROP_OSGI_INSTANCE_AREA, writableArea.resolve(DATA).toUri().toString()); OsgiRuntimeContext runtimeContext = new OsgiRuntimeContext(config); runtimeContexts.put(relPath, runtimeContext); @@ -177,6 +149,21 @@ public class RuntimeManagerMain implements RuntimeManager { OsgiRuntimeContext runtimeContext = loadRuntime(relPath, configCallback); runtimeContext.run(); Framework framework = runtimeContext.getFramework(); + +// for (Bundle b : framework.getBundleContext().getBundles()) { +// try { +//// if (b.getSymbolicName().startsWith("org.eclipse.swt.gtk")) { +//// b.uninstall(); +//// } +//// else if (b.getSymbolicName().startsWith("org.eclipse.jface")) { +//// b.uninstall(); +//// } +// } catch (Exception e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } + if (framework != null) {// in case the framework has closed very quickly after run framework.getBundleContext().addFrameworkListener((e) -> { if (e.getType() >= FrameworkEvent.STOPPED) { diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java index d615678cd..dd6fad2e3 100644 --- a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java +++ b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java @@ -68,7 +68,7 @@ class ThinLogging implements Consumer> { // we don't synchronize maps on purpose as it would be // too expensive during normal operation // updates to the config may be shortly inconsistent - private SortedMap loggers = new TreeMap<>(); + private SortedMap loggers = Collections.synchronizedSortedMap(new TreeMap<>()); private NavigableMap levels = new TreeMap<>(); private volatile boolean updatingConfiguration = false; @@ -191,6 +191,7 @@ class ThinLogging implements Consumer> { } public Logger getLogger(String name, Module module) { + Objects.requireNonNull(name, "logger name"); if (!loggers.containsKey(name)) { ThinLogger logger = new ThinLogger(name, computeApplicableLevel(name)); loggers.put(name, logger); diff --git a/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java b/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java index 0d475ad21..9b9ed6a7a 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiBoot.java @@ -99,19 +99,19 @@ public class OsgiBoot { provisioningManager.registerSource( A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/lib/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/lib/a2" + queryPart); } else if (source.trim().equals(A2Source.DEFAULT_A2_REFERENCE_URI)) { if (Files.exists(homePath)) provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + "://" + homePath.toString() + "/.local/share/a2" + queryPart); provisioningManager .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/share/a2" + queryPart); - provisioningManager - .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart); +// provisioningManager +// .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/lib/a2" + queryPart); provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/share/a2" + queryPart); - provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart); +// provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/lib/a2" + queryPart); } else { provisioningManager.registerSource(source + queryPart); } diff --git a/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java b/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java index ecfeca74e..268fb221b 100644 --- a/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java +++ b/org.argeo.init/src/org/argeo/init/osgi/OsgiRuntimeContext.java @@ -96,12 +96,21 @@ public class OsgiRuntimeContext implements RuntimeContext, AutoCloseable { } OsgiBoot osgiBoot = new OsgiBoot(bundleContext); String frameworkUuuid = bundleContext.getProperty(Constants.FRAMEWORK_UUID); - new Thread("OSGi boot framework " + frameworkUuuid) { + + // separate thread in order to improve logging + Thread osgiBootThread = new Thread("OSGi boot framework " + frameworkUuuid) { @Override public void run() { osgiBoot.bootstrap(config); } - }.start(); + }; + osgiBootThread.start(); + // TODO return a completable stage so that inits can run in parallel +// try { +// osgiBootThread.join(60 * 1000); +// } catch (InterruptedException e) { +// // silent +// } } public void update() { diff --git a/sdk/argeo-build b/sdk/argeo-build index 6f8e29e85..e021d17c0 160000 --- a/sdk/argeo-build +++ b/sdk/argeo-build @@ -1 +1 @@ -Subproject commit 6f8e29e850f9fcfa5149e296e650355fab930752 +Subproject commit e021d17c09f8586a68177e9eb40d9caa088c37b1 diff --git a/swt/rap/org.argeo.swt.specific.rap/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/swt/rap/org.argeo.swt.specific.rap/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java index 84ab27679..ae7bf49d7 100644 --- a/swt/rap/org.argeo.swt.specific.rap/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java +++ b/swt/rap/org.argeo.swt.specific.rap/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java @@ -1,9 +1,5 @@ package org.argeo.eclipse.ui.specific; -import org.eclipse.jface.viewers.AbstractTableViewer; -import org.eclipse.jface.viewers.ColumnViewer; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.Viewer; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.widgets.Widget; @@ -27,14 +23,6 @@ public class EclipseUiSpecificUtils { widget.setData("org.eclipse.rap.rwt.markupValidationDisabled", Boolean.TRUE); } - /** - * TootlTip support is supported only for {@link AbstractTableViewer} in RAP - */ - public static void enableToolTipSupport(Viewer viewer) { - if (viewer instanceof ColumnViewer) - ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer); - } - private EclipseUiSpecificUtils() { } } diff --git a/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java index 77aeae061..7af1456b7 100644 --- a/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java +++ b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpApp.java @@ -81,20 +81,24 @@ public class CmsRcpApp extends AbstractSwtCmsView implements CmsView { // Styling CmsTheme theme = CmsSwtUtils.getCmsTheme(parent); if (theme != null) { - cssEngine = new CSSSWTEngineImpl(display); - for (String path : theme.getSwtCssPaths()) { - try (InputStream in = theme.loadPath(path)) { - cssEngine.parseStyleSheet(in); - } catch (IOException e) { - throw new IllegalStateException("Cannot load stylesheet " + path, e); + try { + cssEngine = new CSSSWTEngineImpl(display); + for (String path : theme.getSwtCssPaths()) { + try (InputStream in = theme.loadPath(path)) { + cssEngine.parseStyleSheet(in); + } catch (IOException e) { + throw new IllegalStateException("Cannot load stylesheet " + path, e); + } } + cssEngine.setErrorHandler(new CSSErrorHandler() { + public void error(Exception e) { + log.error("SWT styling error: ", e); + } + }); + applyStyles(shell); + } catch (Throwable e) {// could be a class not found error + log.error("Cannot initialise RCP theming", e); } - cssEngine.setErrorHandler(new CSSErrorHandler() { - public void error(Exception e) { - log.error("SWT styling error: ", e); - } - }); - applyStyles(shell); } shell.layout(true, true); diff --git a/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpDisplayFactory.java b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpDisplayFactory.java index cd554de9d..96de08e10 100644 --- a/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpDisplayFactory.java +++ b/swt/rcp/org.argeo.cms.swt.rcp/src/org/argeo/cms/ui/rcp/CmsRcpDisplayFactory.java @@ -61,15 +61,18 @@ public class CmsRcpDisplayFactory { public void run() { try { display = Display.getDefault(); - display.setRuntimeExceptionHandler((e) -> e.printStackTrace()); - display.setErrorHandler((e) -> e.printStackTrace()); - - while (!shutdown) { - if (!display.readAndDispatch()) - display.sleep(); + boolean displayOwner = display.getThread() == this; + if (displayOwner) { + display.setRuntimeExceptionHandler((e) -> e.printStackTrace()); + display.setErrorHandler((e) -> e.printStackTrace()); + + while (!shutdown) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + display = null; } - display.dispose(); - display = null; } catch (UnsatisfiedLinkError e) { logger.log(Level.ERROR, "Cannot load SWT, either because the SWT DLLs are no in the java.library.path," @@ -79,6 +82,7 @@ public class CmsRcpDisplayFactory { } } + @Deprecated public Display getDisplay() { return display; } diff --git a/swt/rcp/org.argeo.swt.specific.rcp/bnd.bnd b/swt/rcp/org.argeo.swt.specific.rcp/bnd.bnd index bb88efda7..23ea12bc1 100644 --- a/swt/rcp/org.argeo.swt.specific.rcp/bnd.bnd +++ b/swt/rcp/org.argeo.swt.specific.rcp/bnd.bnd @@ -1,20 +1,18 @@ Import-Package: \ -!java.*,\ -org.apache.commons.io,\ -org.eclipse.core.commands,\ +org.eclipse.core.commands;resolution:=optional,\ !org.eclipse.core.runtime,\ !org.eclipse.ui.plugin,\ org.eclipse.swt,\ -javax.servlet.http;version="[3,5)",\ -javax.servlet;version="[3,5)",\ +javax.servlet.http;resolution:=optional,\ +javax.servlet;resolution:=optional,\ * Export-Package: org.argeo.*,\ org.eclipse.rap.fileupload.*;version="3.10",\ org.eclipse.rap.rwt.*;version="3.10" -# Was !org.eclipse.core.commands,\ why ? +# Was !org.eclipse.core.commands, why ? -#Bundle-Activator: org.argeo.eclipse.ui.ArgeoUiPlugin +Bundle-Activator: org.argeo.internal.swt.specific.osgi.SwtSpecificRcpActivator #Bundle-ActivationPolicy: lazy #Ignore-Package: org.eclipse.core.commands \ No newline at end of file diff --git a/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java index 47ff35dc0..b99fd5815 100644 --- a/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java +++ b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/rcp/internal/rwt/RcpResourceManager.java @@ -1,13 +1,11 @@ package org.argeo.eclipse.ui.rcp.internal.rwt; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.Map; import java.util.TreeMap; -import org.argeo.cms.util.StreamUtils; import org.eclipse.rap.rwt.service.ResourceManager; public class RcpResourceManager implements ResourceManager { @@ -15,11 +13,13 @@ public class RcpResourceManager implements ResourceManager { @Override public void register(String name, InputStream in) { - try { - register.put(name, StreamUtils.toByteArray(in)); - } catch (IOException e) { - throw new RuntimeException("Cannot register " + name, e); - } + // FIXME implement it + throw new UnsupportedOperationException(); +// try { +// register.put(name, StreamUtils.toByteArray(in)); +// } catch (IOException e) { +// throw new RuntimeException("Cannot register " + name, e); +// } } @Override diff --git a/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java index d1acbcfc0..11969b3eb 100644 --- a/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java +++ b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/eclipse/ui/specific/EclipseUiSpecificUtils.java @@ -1,8 +1,5 @@ package org.argeo.eclipse.ui.specific; -import org.eclipse.jface.viewers.ColumnViewer; -import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; -import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Widget; /** Static utilities to bridge differences between RCP and RAP */ @@ -25,16 +22,6 @@ public class EclipseUiSpecificUtils { // does nothing } - /** - * TootlTip support is supported for {@link ColumnViewer} in RCP - * - * @see ColumnViewerToolTipSupport#enableFor(Viewer) - */ - public static void enableToolTipSupport(Viewer viewer) { - if (viewer instanceof ColumnViewer) - ColumnViewerToolTipSupport.enableFor((ColumnViewer) viewer); - } - private EclipseUiSpecificUtils() { } } diff --git a/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/internal/swt/specific/osgi/SwtSpecificRcpActivator.java b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/internal/swt/specific/osgi/SwtSpecificRcpActivator.java new file mode 100644 index 000000000..e74e1095f --- /dev/null +++ b/swt/rcp/org.argeo.swt.specific.rcp/src/org/argeo/internal/swt/specific/osgi/SwtSpecificRcpActivator.java @@ -0,0 +1,75 @@ +package org.argeo.internal.swt.specific.osgi; + +import org.eclipse.swt.SWTError; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class SwtSpecificRcpActivator implements BundleActivator { + private static Display display; + private static Shell rootShell; + private static UiThread uiThread; + + private static boolean debug = true; + + @Override + public void start(BundleContext context) throws Exception { + if (display != null) + throw new IllegalStateException("SWT display already exists"); + uiThread = new UiThread(); + uiThread.start(); + } + + @Override + public void stop(BundleContext context) throws Exception { + if (display == null) + return; // TODO log issue + display.asyncExec(() -> rootShell.dispose()); + display.wake(); + uiThread.join(60 * 1000); + uiThread = null; + display = null; + } + + static class UiThread extends Thread { + + @Override + public void run() { + boolean displayOwner = true; + Display d = Display.getDefault(); + if (d.getThread() != UiThread.this) { + displayOwner = false; + // throw new IllegalStateException("There was already a default SWT display"); + } + + d.syncExec(() -> { + try { + rootShell = new Shell(d); + } catch (SWTError e) { + e.printStackTrace(); + display.dispose(); + return; + } + + if (debug) { + rootShell.setLayout(new FillLayout()); + new Label(rootShell, 0).setText("ROOT SHELL"); + rootShell.pack(); + rootShell.open(); + } + }); + + display = d; + + if (displayOwner) { + while (!rootShell.isDisposed()) + if (!display.readAndDispatch()) + display.sleep(); + display.dispose(); + } + } + } +}