| /*=============================================================================# |
| # Copyright (c) 2009, 2018 Stephan Wahlbrink and others. |
| # |
| # 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, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.rj.eclient.graphics; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| import org.eclipse.core.runtime.ISafeRunnable; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.SafeRunner; |
| import org.eclipse.core.runtime.preferences.IPreferencesService; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Display; |
| |
| import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet; |
| import org.eclipse.statet.jcommons.collections.ImIdentityList; |
| import org.eclipse.statet.jcommons.collections.ImList; |
| |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.rj.eclient.graphics.ERGraphic; |
| import org.eclipse.statet.rj.eclient.graphics.ERGraphicsManager; |
| import org.eclipse.statet.rj.eclient.graphics.RGraphics; |
| import org.eclipse.statet.rj.eclient.graphics.RGraphicsPreferencePage; |
| import org.eclipse.statet.rj.eclient.graphics.comclient.ToolRClientGraphicActions; |
| import org.eclipse.statet.rj.server.client.RClientGraphic; |
| import org.eclipse.statet.rj.server.client.RClientGraphicActions; |
| import org.eclipse.statet.rj.server.client.RClientGraphicFactory; |
| |
| |
| /** |
| * Factory and manager implementation for R graphics under Eclipse. |
| * <p> |
| * Public class is {@link org.eclipse.statet.rj.eclient.graphics.comclient.ERGraphicFactory}.</p> |
| */ |
| public class EclipseRGraphicFactory implements RClientGraphicFactory, ERGraphicsManager { |
| |
| |
| private static class AddedSafeRunnable implements ISafeRunnable { |
| |
| ERGraphic graphic; |
| ERGraphicsManager.Listener listener; |
| |
| @Override |
| public void run() { |
| this.listener.graphicAdded(this.graphic); |
| } |
| |
| @Override |
| public void handleException(final Throwable exception) { |
| // RGraphicsPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, RGraphicsPlugin.BUNDLE_ID, 0, |
| // "An error occurred when notifying.", exception)); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| private static class RemovedSafeRunnable implements ISafeRunnable { |
| |
| ERGraphic graphic; |
| ERGraphicsManager.Listener listener; |
| |
| @Override |
| public void run() { |
| this.listener.graphicRemoved(this.graphic); |
| } |
| |
| @Override |
| public void handleException(final Throwable exception) { |
| } |
| |
| } |
| |
| private static class ShowSafeRunnable implements ISafeRunnable { |
| |
| ERGraphic graphic; |
| ERGraphicsManager.ListenerShowExtension listener; |
| |
| int bestPriority; |
| ERGraphicsManager.ListenerShowExtension bestListener; |
| |
| @Override |
| public void run() { |
| if (this.listener != null) { |
| final int priority= this.listener.canShowGraphic(this.graphic); |
| if (priority > this.bestPriority) { |
| this.bestPriority= priority; |
| this.bestListener= this.listener; |
| } |
| } |
| else { |
| this.bestListener.showGraphic(this.graphic); |
| } |
| } |
| |
| @Override |
| public void handleException(final Throwable exception) { |
| // RGraphicsPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, RGraphicsPlugin.BUNDLE_ID, 0, |
| // "An error occurred when notifying.", exception)); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| |
| private final CopyOnWriteIdentityListSet<EclipseRGraphic> graphics= new CopyOnWriteIdentityListSet<>(); |
| |
| private final CopyOnWriteIdentityListSet<ERGraphicsManager.Listener> listeners= new CopyOnWriteIdentityListSet<>(); |
| private final AddedSafeRunnable addedRunnable= new AddedSafeRunnable(); |
| private final RemovedSafeRunnable removedRunnable= new RemovedSafeRunnable(); |
| private final ShowSafeRunnable showRunnable= new ShowSafeRunnable(); |
| |
| private final Display defaultDisplay; |
| private final FontManager fontManager; |
| private final ColorManager colorManager; |
| |
| |
| public EclipseRGraphicFactory() { |
| this.defaultDisplay= UIAccess.getDisplay(); |
| this.fontManager= new FontManager(this.defaultDisplay); |
| this.colorManager= new ColorManager(this.defaultDisplay); |
| this.defaultDisplay.asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| EclipseRGraphicFactory.this.defaultDisplay.disposeExec(new Runnable() { |
| @Override |
| public void run() { |
| EclipseRGraphicFactory.this.fontManager.dispose(); |
| EclipseRGraphicFactory.this.colorManager.dispose(); |
| } |
| }); |
| } |
| }); |
| } |
| |
| |
| @Override |
| public Map<String, ? extends Object> getInitServerProperties() { |
| final Map<String, Object> map= new HashMap<>(); |
| final IPreferencesService preferences= Platform.getPreferencesService(); |
| final AtomicReference<double[]> dpi= new AtomicReference<>(); |
| dpi.set(RGraphicsPreferencePage.parseDPI(preferences.getString( |
| RGraphics.PREF_DISPLAY_QUALIFIER, RGraphics.PREF_DISPLAY_CUSTOM_DPI_KEY, null, null ))); |
| if (dpi.get() == null) { |
| Display.getDefault().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| final Point point= Display.getCurrent().getDPI(); |
| dpi.set(new double[] { point.x, point.y }); |
| } |
| }); |
| if (dpi.get() == null) { |
| dpi.set(new double[] { 96.0, 96.0 }); |
| } |
| } |
| map.put("display.ppi", dpi.get()); //$NON-NLS-1$ |
| return map; |
| } |
| |
| @Override |
| public RClientGraphic newGraphic(final int devId, final double w, final double h, |
| final RClientGraphic.InitConfig config, |
| final boolean active, final RClientGraphicActions actions, final int options) { |
| final EclipseRGraphic egraphic= new EclipseRGraphic(devId, w, h, config, active, |
| (actions instanceof ToolRClientGraphicActions) ? (ToolRClientGraphicActions) actions : null, |
| options, this ); |
| if ((options & MANAGED_OFF) == 0) { |
| this.defaultDisplay.syncExec(new Runnable() { |
| @Override |
| public void run() { |
| EclipseRGraphicFactory.this.graphics.add(egraphic); |
| final ImIdentityList<Listener> listeners= EclipseRGraphicFactory.this.listeners.toList(); |
| |
| EclipseRGraphicFactory.this.showRunnable.graphic= egraphic; |
| EclipseRGraphicFactory.this.showRunnable.bestPriority= Integer.MIN_VALUE; |
| for (final Listener listener : listeners) { |
| if (listener instanceof ListenerShowExtension) { |
| EclipseRGraphicFactory.this.showRunnable.listener= (ListenerShowExtension) listener; |
| SafeRunner.run(EclipseRGraphicFactory.this.showRunnable); |
| } |
| } |
| EclipseRGraphicFactory.this.showRunnable.listener= null; |
| if (EclipseRGraphicFactory.this.showRunnable.bestPriority >= 0) { |
| SafeRunner.run(EclipseRGraphicFactory.this.showRunnable); |
| } |
| EclipseRGraphicFactory.this.showRunnable.bestListener= null; |
| EclipseRGraphicFactory.this.showRunnable.graphic= null; |
| |
| EclipseRGraphicFactory.this.addedRunnable.graphic= egraphic; |
| for (final Listener listener : listeners) { |
| EclipseRGraphicFactory.this.addedRunnable.listener= listener; |
| SafeRunner.run(EclipseRGraphicFactory.this.addedRunnable); |
| } |
| EclipseRGraphicFactory.this.addedRunnable.listener= null; |
| EclipseRGraphicFactory.this.addedRunnable.graphic= null; |
| } |
| }); |
| } |
| return egraphic; |
| } |
| |
| @Override |
| public void closeGraphic(final RClientGraphic graphic) { |
| final EclipseRGraphic egraphic= (EclipseRGraphic) graphic; |
| close(egraphic); |
| egraphic.closeFromR(); |
| } |
| |
| void close(final EclipseRGraphic graphic) { |
| if (!this.defaultDisplay.isDisposed()) { |
| this.defaultDisplay.syncExec(new Runnable() { |
| @Override |
| public void run() { |
| EclipseRGraphicFactory.this.graphics.remove(graphic); |
| final ImIdentityList<Listener> listeners= EclipseRGraphicFactory.this.listeners.toList(); |
| |
| EclipseRGraphicFactory.this.removedRunnable.graphic= graphic; |
| for (final Listener listener : listeners) { |
| EclipseRGraphicFactory.this.removedRunnable.listener= listener; |
| SafeRunner.run(EclipseRGraphicFactory.this.removedRunnable); |
| } |
| EclipseRGraphicFactory.this.removedRunnable.listener= null; |
| EclipseRGraphicFactory.this.removedRunnable.graphic= null; |
| } |
| }); |
| } |
| } |
| |
| |
| public FontManager getFontManager(final Display display) { |
| if (display == this.defaultDisplay) { |
| return this.fontManager; |
| } |
| return null; |
| } |
| |
| public ColorManager getColorManager(final Display display) { |
| if (display == this.defaultDisplay) { |
| return this.colorManager; |
| } |
| return null; |
| } |
| |
| |
| @Override |
| public ImList<? extends ERGraphic> getAllGraphics() { |
| return this.graphics.toList(); |
| } |
| |
| @Override |
| public void addListener(final Listener listener) { |
| this.listeners.add(listener); |
| } |
| |
| @Override |
| public void removeListener(final Listener listener) { |
| this.listeners.remove(listener); |
| } |
| |
| } |