/* * Copyright 2000-2009 JetBrains s.r.o. * * Licensed 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 com.intellij.ide.util.projectWizard; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.util.concurrency.SwingWorker; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.UiNotifyConnector; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author nik */ public abstract class AbstractStepWithProgress<Result> extends ModuleWizardStep { @NonNls private static final String PROGRESS_PANEL = "progress_panel"; @NonNls private static final String RESULTS_PANEL = "results_panel"; private JPanel myPanel; private JLabel myTitleLabel; private JLabel myProgressLabel; private JLabel myProgressLabel2; private ProgressIndicator myProgressIndicator = null; private final String myPromptStopSearch; public AbstractStepWithProgress(final String promptStopSearching) { myPromptStopSearch = promptStopSearching; } public final JComponent getComponent() { if (myPanel == null) { myPanel = new JPanel(new CardLayout()); myPanel.setBorder(BorderFactory.createEtchedBorder()); myPanel.add(createProgressPanel(), PROGRESS_PANEL); myPanel.add(createResultsPanel(), RESULTS_PANEL); } return myPanel; } protected abstract JComponent createResultsPanel(); protected abstract String getProgressText(); protected abstract boolean shouldRunProgress(); protected abstract Result calculate(); protected abstract void onFinished(Result result, boolean canceled); private JPanel createProgressPanel() { final JPanel progressPanel = new JPanel(new GridBagLayout()); myTitleLabel = new JLabel(); myTitleLabel.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD)); progressPanel.add(myTitleLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(8, 10, 5, 10), 0, 0)); myProgressLabel = new JLabel(); progressPanel.add(myProgressLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(8, 10, 0, 10), 0, 0)); myProgressLabel2 = new JLabel(); progressPanel.add(myProgressLabel2, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(8, 10, 0, 10), 0, 0)); JButton stopButton = new JButton(IdeBundle.message("button.stop.searching")); stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { cancelSearch(); } }); progressPanel.add(stopButton, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 2, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 0, 0, 10), 0, 0)); return progressPanel; } private void cancelSearch() { if (myProgressIndicator != null) { myProgressIndicator.cancel(); } } private synchronized boolean isProgressRunning() { return myProgressIndicator != null && myProgressIndicator.isRunning(); } public void updateStep(@NotNull WizardContext wizardContext) { if (shouldRunProgress()) { runProgress(); } else { showCard(RESULTS_PANEL); } } protected void runProgress() { final MyProgressIndicator progress = new MyProgressIndicator(); progress.setModalityProgress(null); final String title = getProgressText(); if (title != null) { myTitleLabel.setText(title); } showCard(PROGRESS_PANEL); myProgressIndicator = progress; if (ApplicationManager.getApplication().isUnitTestMode()) { Result result = ProgressManager.getInstance().runProcess(new Computable<Result>() { @Override public Result compute() { return calculate(); } }, progress); onFinished(result, false); return; } UiNotifyConnector.doWhenFirstShown(myPanel, new Runnable() { @Override public void run() { new SwingWorker() { public Object construct() { final Ref<Result> result = Ref.create(null); ProgressManager.getInstance().runProcess(new Runnable() { public void run() { result.set(calculate()); } }, progress); return result.get(); } public void finished() { myProgressIndicator = null; ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { final Result result = (Result)get(); onFinished(result, progress.isCanceled()); showCard(RESULTS_PANEL); } }); } }.start(); } }); } private void showCard(final String id) { ((CardLayout)myPanel.getLayout()).show(myPanel, id); myPanel.revalidate(); } public boolean validate(@NotNull WizardContext wizardContext) throws ConfigurationException { if (isProgressRunning()) { final int answer = Messages.showOkCancelDialog(getComponent(), myPromptStopSearch, IdeBundle.message("title.question"), IdeBundle.message("action.continue.searching"), IdeBundle.message("action.stop.searching"), Messages.getWarningIcon()); if (answer == 1) { // terminate cancelSearch(); } return false; } return true; } public void onStepLeaving(@NotNull WizardContext wizardContext) { if (isProgressRunning()) { cancelSearch(); } } protected class MyProgressIndicator extends ProgressIndicatorBase { public void setText(String text) { updateLabel(myProgressLabel, text); super.setText(text); } public void setText2(String text) { updateLabel(myProgressLabel2, text); super.setText2(text); } private void updateLabel(final JLabel label, final String text) { UIUtil.invokeLaterIfNeeded(new Runnable() { public void run() { label.setText(text); } }); } } }