foundation project generator: avoid file downloadings in tests
[idea/community.git] / platform / lang-impl / src / com / intellij / lang / javascript / boilerplate / GithubProjectGeneratorPeer.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.lang.javascript.boilerplate;
17
18 import com.google.common.collect.Sets;
19 import com.intellij.BundleBase;
20 import com.intellij.ide.util.projectWizard.SettingsStep;
21 import com.intellij.openapi.ui.ValidationInfo;
22 import com.intellij.openapi.util.text.StringUtil;
23 import com.intellij.platform.WebProjectGenerator;
24 import com.intellij.platform.templates.github.GithubTagInfo;
25 import com.intellij.ui.ListCellRendererWrapper;
26 import com.intellij.util.ObjectUtils;
27 import com.intellij.util.containers.ContainerUtil;
28 import com.intellij.util.ui.ReloadableComboBoxPanel;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
31
32 import javax.swing.*;
33 import java.util.*;
34
35 /**
36  * @author Sergey Simonchik
37  */
38 public class GithubProjectGeneratorPeer implements WebProjectGenerator.GeneratorPeer<GithubTagInfo> {
39   private void createUIComponents() {
40     myReloadableComboBoxPanel = new ReloadableComboBoxPanel<GithubTagInfo>() {
41
42       @SuppressWarnings("unchecked")
43       @Override
44       protected void doUpdateValues(@NotNull Set<GithubTagInfo> tags) {
45         if (!shouldUpdate(tags)) {
46           return;
47         }
48
49         List<GithubTagInfo> sortedTags = createSortedTagList(tags);
50         GithubTagInfo selectedItem = getSelectedValue();
51         if (selectedItem == null && sortedTags.size() > 0) {
52           selectedItem = sortedTags.get(0);
53         }
54         myComboBox.removeAllItems();
55         myComboBox.addItem(myMasterTag);
56         for (GithubTagInfo tag : sortedTags) {
57           myComboBox.addItem(tag);
58         }
59         if (selectedItem != null) {
60           // restore previously selected item
61           for (int i = 0; i < myComboBox.getItemCount(); i++) {
62             GithubTagInfo item = GithubTagInfo.tryCast(myComboBox.getItemAt(i));
63             if (item != null && item.getName().equals(selectedItem.getName())) {
64               myComboBox.setSelectedIndex(i);
65               break;
66             }
67           }
68         }
69         myComboBox.updateUI();
70         fireStateChanged();
71       }
72
73       private boolean shouldUpdate(Set<GithubTagInfo> newTags) {
74         if (myComboBox.getItemCount() == 0) {
75           return true;
76         }
77         int count = myComboBox.getItemCount();
78         Set<GithubTagInfo> oldTags = Sets.newHashSet();
79         for (int i = 1; i < count; i++) {
80           GithubTagInfo item = ObjectUtils.tryCast(myComboBox.getItemAt(i), GithubTagInfo.class);
81           if (item != null) {
82             oldTags.add(item);
83           }
84         }
85         return !oldTags.equals(newTags);
86       }
87
88       @SuppressWarnings("unchecked")
89       @NotNull
90       @Override
91       protected JComboBox createValuesComboBox() {
92         JComboBox box = super.createValuesComboBox();
93         box.setRenderer(new ListCellRendererWrapper<GithubTagInfo>() {
94           @Override
95           public void customize(JList list, GithubTagInfo tag, int index, boolean selected, boolean hasFocus) {
96             final String text;
97             if (tag == null) {
98               text = isBackgroundJobRunning() ? "Loading..." : "Unavailable";
99             }
100             else {
101               text = tag.getName();
102             }
103             setText(text);
104           }
105         });
106
107         return box;
108       }
109     };
110
111     myVersionPanel = myReloadableComboBoxPanel.getMainPanel();
112   }
113
114   private final List<WebProjectGenerator.SettingsStateListener> myListeners = ContainerUtil.newArrayList();
115   private final GithubTagInfo myMasterTag;
116   private final GithubTagListProvider myTagListProvider;
117   private JComponent myComponent;
118   private JPanel myVersionPanel;
119   private ReloadableComboBoxPanel<GithubTagInfo> myReloadableComboBoxPanel;
120
121   public GithubProjectGeneratorPeer(@NotNull AbstractGithubTagDownloadedProjectGenerator generator) {
122     String ghUserName = generator.getGithubUserName();
123     String ghRepoName = generator.getGithubRepositoryName();
124     myMasterTag = new GithubTagInfo(
125       "master",
126       String.format("https://github.com/%s/%s/zipball/master", ghUserName, ghRepoName)
127     );
128
129     myTagListProvider = new GithubTagListProvider(ghUserName, ghRepoName);
130
131     myReloadableComboBoxPanel.setDataProvider(new ReloadableComboBoxPanel.DataProvider<GithubTagInfo>() {
132       @Override
133       public Set<GithubTagInfo> getCachedValues() {
134         return myTagListProvider.getCachedTags();
135       }
136
137       @Override
138       public void updateValuesAsynchronously() {
139         myTagListProvider.updateTagListAsynchronously(GithubProjectGeneratorPeer.this);
140       }
141     });
142
143     myReloadableComboBoxPanel.reloadValuesInBackground();
144   }
145
146   void onTagsUpdated(@NotNull Set<GithubTagInfo> tags) {
147     myReloadableComboBoxPanel.onUpdateValues(tags);
148   }
149
150   void onTagsUpdateError(@NotNull final String errorMessage) {
151     myReloadableComboBoxPanel.onValuesUpdateError(errorMessage);
152   }
153
154   @NotNull
155   private static List<GithubTagInfo> createSortedTagList(@NotNull Collection<GithubTagInfo> tags) {
156     List<GithubTagInfo> sortedTags = ContainerUtil.newArrayList(tags);
157     Collections.sort(sortedTags, new Comparator<GithubTagInfo>() {
158       @Override
159       public int compare(GithubTagInfo tag1, GithubTagInfo tag2) {
160         GithubTagInfo.Version v1 = tag1.getVersion();
161         GithubTagInfo.Version v2 = tag2.getVersion();
162         return v2.compareTo(v1);
163       }
164     });
165     for (GithubTagInfo tag : sortedTags) {
166       tag.setRecentTag(false);
167     }
168     if (!sortedTags.isEmpty()) {
169       sortedTags.get(0).setRecentTag(true);
170     }
171     return sortedTags;
172   }
173
174
175   @NotNull
176   @Override
177   public JComponent getComponent() {
178     return myComponent;
179   }
180
181   @Override
182   public void buildUI(@NotNull SettingsStep settingsStep) {
183     settingsStep.addSettingsField(BundleBase.replaceMnemonicAmpersand("&Version:"), myVersionPanel);
184     settingsStep.addSettingsComponent(myReloadableComboBoxPanel.getErrorComponent());
185   }
186
187   @NotNull
188   @Override
189   public GithubTagInfo getSettings() {
190     GithubTagInfo tag = myReloadableComboBoxPanel.getSelectedValue();
191     if (tag == null) {
192       throw new RuntimeException("[internal error] No versions available.");
193     }
194     return tag;
195   }
196
197   @Override
198   @Nullable
199   public ValidationInfo validate() {
200     GithubTagInfo tag = myReloadableComboBoxPanel.getSelectedValue();
201     if (tag != null) {
202       return null;
203     }
204     String errorMessage = StringUtil.notNullize(myReloadableComboBoxPanel.getErrorComponent().getText());
205     if (errorMessage.isEmpty()) {
206       errorMessage = "Versions have not been loaded yet.";
207     }
208     return new ValidationInfo(errorMessage);
209   }
210
211   @Override
212   public boolean isBackgroundJobRunning() {
213     return myReloadableComboBoxPanel.isBackgroundJobRunning();
214   }
215
216   @Override
217   public void addSettingsStateListener(@NotNull WebProjectGenerator.SettingsStateListener listener) {
218     myListeners.add(listener);
219   }
220
221
222   private void fireStateChanged() {
223     GithubTagInfo tag = myReloadableComboBoxPanel.getSelectedValue();
224     for (WebProjectGenerator.SettingsStateListener listener : myListeners) {
225       listener.stateChanged(tag != null);
226     }
227   }
228 }