blob: 9046c19caccc158b5f58456ac907f1b11a1b8b6b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.api.java.source.ui;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Future;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import org.netbeans.api.java.platform.JavaPlatform;
import org.netbeans.api.java.source.ClasspathInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.SourceUtils;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/**
* Support for notifying user about the background scan.
* @since 1.2
* @author Tomas Zezula
*/
public class ScanDialog {
private ScanDialog () {}
/**
* This is a helper method to provide support for delaying invocations of actions
* depending on java model.
* <br>Behavior of this method is following:<br>
* If classpath scanning is not in progress, runnable's run() is called. <br>
* If classpath scanning is in progress, modal cancellable notification dialog with specified
* tile is opened.
* </ul>
* As soon as classpath scanning finishes, this dialog is closed and runnable's run() is called.
* This method must be called in AWT EventQueue. Runnable is performed in AWT thread.
*
* @param runnable Runnable instance which will be called.
* @param actionName Title of wait dialog.
* @return true action was cancelled <br>
* false action was performed
*
* @see org.netbeans.api.java.source.JavaSource#runWhenScanFinished which provides delayed invocation
* of action without UI notification.
*/
public static boolean runWhenScanFinished (final Runnable runnable, final String actionName) {
assert runnable != null;
assert actionName != null;
assert SwingUtilities.isEventDispatchThread();
if (SourceUtils.isScanInProgress()) {
class AL implements ActionListener {
private Dialog dialog;
private Future<Void> monitor;
public synchronized void start (final Future<Void> monitor) {
assert monitor != null;
this.monitor = monitor;
if (dialog != null) {
dialog.setVisible(true);
}
}
public void actionPerformed(ActionEvent e) {
monitor.cancel(false);
close ();
}
synchronized void close () {
if (dialog != null) {
dialog.setVisible(false);
dialog.dispose();
dialog = null;
}
}
};
final AL listener = new AL ();
JLabel label = new JLabel(NbBundle.getMessage(ScanDialog.class,"MSG_WaitScan"),
javax.swing.UIManager.getIcon("OptionPane.informationIcon"), SwingConstants.LEFT);
label.setBorder(new EmptyBorder(12,12,11,11));
DialogDescriptor dd = new DialogDescriptor(label, actionName, true, new Object[]{NbBundle.getMessage(ScanDialog.class,"LBL_CancelAction",actionName)}, null, 0, null, listener);
listener.dialog = DialogDisplayer.getDefault().createDialog(dd);
listener.dialog.pack();
final ClasspathInfo info = ClasspathInfo.create(JavaPlatform.getDefault().getBootstrapLibraries(),
ClassPathSupport.createClassPath(new URL[0]),
ClassPathSupport.createClassPath(new URL[0]));
final JavaSource js = JavaSource.create(info);
try {
final Future<Void> monitor = js.runWhenScanFinished((cc) -> {
final Runnable r = () -> {
listener.close();
runnable.run();
};
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}, true);
if (!monitor.isDone()) {
listener.start(monitor);
}
return monitor.isCancelled();
}catch (IOException e) {
Exceptions.printStackTrace(e);
return true;
}
} else {
runnable.run();
return false;
}
}
}