cleanup: remove useless '@author nik' from javadoc comments
[idea/community.git] / java / idea-ui / src / com / intellij / ide / util / projectWizard / AbstractStepWithProgress.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.ide.util.projectWizard;
4
5 import com.intellij.ide.IdeBundle;
6 import com.intellij.openapi.application.ApplicationManager;
7 import com.intellij.openapi.diagnostic.Logger;
8 import com.intellij.openapi.options.ConfigurationException;
9 import com.intellij.openapi.progress.ProgressIndicator;
10 import com.intellij.openapi.progress.ProgressManager;
11 import com.intellij.openapi.progress.util.ProgressIndicatorBase;
12 import com.intellij.openapi.ui.Messages;
13 import com.intellij.openapi.util.Ref;
14 import com.intellij.openapi.util.text.StringUtil;
15 import com.intellij.util.concurrency.SwingWorker;
16 import com.intellij.util.ui.JBUI;
17 import com.intellij.util.ui.StartupUiUtil;
18 import com.intellij.util.ui.UIUtil;
19 import com.intellij.util.ui.update.UiNotifyConnector;
20 import org.jetbrains.annotations.NonNls;
21 import org.jetbrains.annotations.TestOnly;
22
23 import javax.swing.*;
24 import java.awt.*;
25
26 import static java.awt.GridBagConstraints.*;
27
28 public abstract class AbstractStepWithProgress<Result> extends ModuleWizardStep {
29   private static final Logger LOG = Logger.getInstance(AbstractStepWithProgress.class);
30   @NonNls private static final String PROGRESS_PANEL = "progress_panel";
31   @NonNls private static final String RESULTS_PANEL = "results_panel";
32   private JPanel myPanel;
33
34   private JLabel myTitleLabel;
35   private JLabel myProgressLabel;
36   private JLabel myProgressLabel2;
37   private ProgressIndicator myProgressIndicator;
38   private final String myPromptStopSearch;
39
40   public AbstractStepWithProgress(final String promptStopSearching) {
41     myPromptStopSearch = promptStopSearching;
42   }
43
44   @Override
45   public final JComponent getComponent() {
46     if (myPanel == null) {
47       myPanel = new JPanel(new CardLayout());
48       myPanel.setBorder(BorderFactory.createEtchedBorder());
49
50       myPanel.add(createProgressPanel(), PROGRESS_PANEL);
51       myPanel.add(createResultsPanel(), RESULTS_PANEL);
52     }
53     return myPanel;
54   }
55
56   protected abstract JComponent createResultsPanel();
57
58   protected abstract String getProgressText();
59
60   protected abstract boolean shouldRunProgress();
61
62   protected abstract Result calculate();
63
64   protected abstract void onFinished(Result result, boolean canceled);
65
66   private JPanel createProgressPanel() {
67     final JPanel progressPanel = new JPanel(new GridBagLayout());
68     myTitleLabel = new JLabel();
69     myTitleLabel.setFont(StartupUiUtil.getLabelFont().deriveFont(Font.BOLD));
70     progressPanel.add(myTitleLabel, new GridBagConstraints(0, RELATIVE, 2, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, JBUI.insets(8, 10, 5, 10), 0, 0));
71
72     myProgressLabel = new JLabel();
73     progressPanel.add(myProgressLabel, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 0.0, NORTHWEST, HORIZONTAL, JBUI.insets(8, 10, 0, 10), 0, 0));
74
75     myProgressLabel2 = new JLabel() {
76           @Override
77           public void setText(String text) {
78             super.setText(StringUtil.trimMiddle(text, 80));
79           }
80         };
81     progressPanel.add(myProgressLabel2, new GridBagConstraints(0, RELATIVE, 1, 1, 1.0, 1.0, NORTHWEST, HORIZONTAL, JBUI.insets(8, 10, 0, 10), 0, 0));
82
83     JButton stopButton = new JButton(IdeBundle.message("button.stop.searching"));
84     stopButton.addActionListener(__ -> cancelSearch());
85     progressPanel.add(stopButton, new GridBagConstraints(1, RELATIVE, 1, 2, 0.0, 1.0, NORTHWEST, NONE, JBUI.insets(10, 0, 0, 10), 0, 0));
86     return progressPanel;
87   }
88
89   @TestOnly
90   public void performStep() {
91     Result result = calculate();
92     createResultsPanel();
93     onFinished(result, false);
94     updateDataModel();
95   }
96
97   private void cancelSearch() {
98     if (myProgressIndicator != null) {
99       myProgressIndicator.cancel();
100     }
101   }
102
103   private synchronized boolean isProgressRunning() {
104     return myProgressIndicator != null && myProgressIndicator.isRunning();
105   }
106
107
108   @Override
109   public void updateStep() {
110     if (shouldRunProgress()) {
111       runProgress();
112     }
113     else {
114       showCard(RESULTS_PANEL);
115     }
116   }
117
118   private void runProgress() {
119     final MyProgressIndicator progress = new MyProgressIndicator();
120     progress.setModalityProgress(null);
121     final String title = getProgressText();
122     if (title != null) {
123       myTitleLabel.setText(title);
124     }
125     showCard(PROGRESS_PANEL);
126     myProgressIndicator = progress;
127
128     if (ApplicationManager.getApplication().isUnitTestMode()) {
129
130       Result result = ProgressManager.getInstance().runProcess(() -> calculate(), progress);
131       onFinished(result, false);
132       return;
133     }
134
135     UiNotifyConnector.doWhenFirstShown(myPanel, () -> new SwingWorker<Result>() {
136       @Override
137       public Result construct() {
138         LOG.debug("Start calculation in " + AbstractStepWithProgress.this + " using worker " + toString());
139         final Ref<Result> result = Ref.create(null);
140         ProgressManager.getInstance().runProcess(() -> result.set(calculate()), progress);
141         LOG.debug("Finish calculation in " + AbstractStepWithProgress.this + " using worker " + toString());
142         return result.get();
143       }
144
145       @Override
146       public void finished() {
147         LOG.debug("Schedule showing results for " + AbstractStepWithProgress.this + " using worker " + toString());
148         myProgressIndicator = null;
149         ApplicationManager.getApplication().invokeLater(() -> {
150           LOG.debug("Show results for " + AbstractStepWithProgress.this);
151           final Result result = get();
152           onFinished(result, progress.isCanceled());
153           showCard(RESULTS_PANEL);
154         });
155       }
156     }.start());
157   }
158
159   private void showCard(final String id) {
160     ((CardLayout)myPanel.getLayout()).show(myPanel, id);
161     myPanel.revalidate();
162   }
163
164   @Override
165   public boolean validate() throws ConfigurationException {
166     if (isProgressRunning()) {
167       final int answer = Messages.showOkCancelDialog(getComponent(), myPromptStopSearch,
168                                              IdeBundle.message("title.question"), IdeBundle.message("action.continue.searching"), IdeBundle.message("action.stop.searching"), Messages.getWarningIcon());
169       if (answer != Messages.OK) { // terminate
170         cancelSearch();
171       }
172       return false;
173     }
174     return true;
175   }
176
177   @Override
178   public void onStepLeaving() {
179     if (isProgressRunning()) {
180       cancelSearch();
181     }
182   }
183
184   protected class MyProgressIndicator extends ProgressIndicatorBase {
185     @Override
186     public void setText(String text) {
187       updateLabel(myProgressLabel, text);
188       super.setText(text);
189     }
190
191     @Override
192     public void setText2(String text) {
193       updateLabel(myProgressLabel2, text);
194       super.setText2(text);
195     }
196
197     private void updateLabel(final JLabel label, final String text) {
198       UIUtil.invokeLaterIfNeeded(() -> label.setText(text));
199     }
200   }
201 }