/*=============================================================================#
# Copyright (c) 2015-2016 Stephan Wahlbrink (WalWare.de) and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Stephan Wahlbrink - initial API and implementation
#=============================================================================*/
package de.walware.docmlet.base.internal.ui.viewer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import de.walware.jcommons.collections.ImList;
import de.walware.ecommons.debug.core.util.LaunchConfigurationCollector;
import de.walware.ecommons.io.win.DDE;
import de.walware.ecommons.io.win.DDEClient;
import de.walware.docmlet.base.internal.ui.viewer.DocViewerLaunchConfig.DDETask;
import de.walware.docmlet.base.ui.viewer.DocViewerConfig;
public class DocViewerCloseDelegate extends LaunchConfigurationCollector {
public static boolean isAvailable() {
return DDE.isSupported();
}
private class RestoreRunnable implements Runnable {
private static final int CHECK= 0;
private static final int RESTORE= 1;
private static final int DISPOSED= 2;
private final Display display;
private volatile int run= 0;
private long lastTime= 0;
private Shell activeShell;
public RestoreRunnable(final Display display) {
this.display= display;
}
@Override
public void run() {
switch (this.run) {
case CHECK:
this.run= RESTORE;
this.activeShell= this.display.getActiveShell();
return;
case RESTORE: {
final long diff= (System.nanoTime() - this.lastTime) / 1000000; // milli
if (diff < 500 && this.display.getActiveShell() == null) {
Shell shell= null;
if (!this.activeShell.isDisposed()) {
shell= this.activeShell;
}
else {
final IWorkbenchWindow activeWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWindow == null) {
dispose(true);
return;
}
shell= activeWindow.getShell();
}
if (shell != null && !shell.isDisposed()) {
shell.forceActive();
}
}
else if (diff < 200) {
this.display.timerExec(50, this);
return;
}
dispose(true);
return;
}
default:
return;
}
}
public void runCheck() {
if (this.display != null) {
this.display.syncExec(this);
}
}
public void setLastOK(final long time) {
this.lastTime= time;
}
public void dispose(final boolean remove) {
this.run= DISPOSED;
if (remove) {
synchronized (DocViewerCloseDelegate.this.restoreRunnables) {
DocViewerCloseDelegate.this.restoreRunnables.remove(this);
}
}
}
public void scheduleRestore() {
if (this.display != null && this.run > 0
&& this.lastTime != 0 && this.activeShell != null) {
synchronized (DocViewerCloseDelegate.this.restoreRunnables) {
DocViewerCloseDelegate.this.restoreRunnables.add(this);
}
this.display.asyncExec(this);
}
}
}
private final List<RestoreRunnable> restoreRunnables= new ArrayList<>();
public DocViewerCloseDelegate() {
super(DocViewerConfig.TYPE_ID);
}
@Override
protected boolean include(final ILaunchConfiguration configuration) throws CoreException {
return (super.include(configuration)
&& !configuration.getAttribute(DocViewerConfig.TASK_PRE_PRODUCE_OUTPUT_ATTR_QUALIFIER + '/' +
DocViewerConfig.DDE_COMMAND_ATTR_KEY, "" ).isEmpty() ); //$NON-NLS-1$
}
public void run(final DocViewerLaunchConfig config, final SubMonitor m) throws CoreException {
final ImList<ILaunchConfiguration> configurations= getConfigurations();
if (configurations.isEmpty()) {
return;
}
int workRemaining= configurations.size() * 2;
m.beginTask(Messages.PreProduceOutput_task, workRemaining);
final RestoreRunnable runnable= new RestoreRunnable(Display.getDefault());
runnable.runCheck();
for (final ILaunchConfiguration configuration : configurations) {
m.setWorkRemaining(workRemaining);
workRemaining-= 2;
if (m.isCanceled()) {
throw new CoreException(Status.CANCEL_STATUS);
}
try {
final DDETask ddeTask= config.loadDDETask(configuration,
DocViewerConfig.TASK_PRE_PRODUCE_OUTPUT_ATTR_QUALIFIER,
Messages.DDE_PreProduceOutput_label, m.newChild(1) );
if (ddeTask != null) {
m.newChild(1);
try {
ddeTask.exec();
runnable.setLastOK(System.nanoTime());
}
catch (final CoreException e) {
switch (e.getStatus().getCode()) {
case DDEClient.INIT_FAILED:
return;
case DDEClient.CONNECT_FAILED:
continue;
default:
throw e;
}
}
}
}
catch (final CoreException e) {
}
}
runnable.scheduleRestore();
}
public void cancelFocus() {
synchronized (this.restoreRunnables) {
for (final RestoreRunnable runnable : this.restoreRunnables) {
runnable.dispose(false);
}
this.restoreRunnables.clear();
}
}
}