blob: d983a29f937931fc3a39ba06e2c3f0e73a44bbfb [file] [log] [blame]
/*=============================================================================#
# 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);
}
}