[project] IDE launcher in Windows jump list instead of the custom one (IDEA-156078)
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / ui / StudyNewProjectPanel.java
1 package com.jetbrains.edu.learning.ui;
2
3 import com.intellij.facet.ui.FacetValidatorsManager;
4 import com.intellij.facet.ui.ValidationResult;
5 import com.intellij.icons.AllIcons;
6 import com.intellij.openapi.fileChooser.FileChooser;
7 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
8 import com.intellij.openapi.project.Project;
9 import com.intellij.openapi.project.ProjectManager;
10 import com.intellij.openapi.ui.DialogWrapper;
11 import com.intellij.openapi.ui.popup.JBPopupFactory;
12 import com.intellij.openapi.ui.popup.ListPopup;
13 import com.intellij.openapi.ui.popup.PopupStep;
14 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
15 import com.intellij.openapi.util.text.StringUtil;
16 import com.intellij.openapi.vfs.VirtualFile;
17 import com.intellij.util.Consumer;
18 import com.jetbrains.edu.learning.StudyUtils;
19 import com.jetbrains.edu.learning.courseFormat.Course;
20 import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
21 import com.jetbrains.edu.learning.stepic.CourseInfo;
22 import com.jetbrains.edu.learning.stepic.EduStepicConnector;
23 import com.jetbrains.edu.learning.stepic.StudySettings;
24 import icons.InteractiveLearningIcons;
25 import org.jetbrains.annotations.NotNull;
26 import org.jetbrains.annotations.Nullable;
27
28 import javax.swing.*;
29 import java.awt.*;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 /**
36  * author: liana
37  * data: 7/31/14.
38  */
39 public class StudyNewProjectPanel{
40   private List<CourseInfo> myAvailableCourses = new ArrayList<CourseInfo>();
41   private JButton myBrowseButton;
42   private JComboBox myCoursesComboBox;
43   private JButton myRefreshButton;
44   private JPanel myContentPanel;
45   private JLabel myAuthorLabel;
46   private JLabel myLabel;
47   private JPanel myInfoPanel;
48   private JTextPane myDescriptionLabel;
49   private final StudyProjectGenerator myGenerator;
50   private static final String CONNECTION_ERROR = "<html>Failed to download courses.<br>Check your Internet connection.</html>";
51   private static final String INVALID_COURSE = "Selected course is invalid";
52   private FacetValidatorsManager myValidationManager;
53
54   public StudyNewProjectPanel(StudyProjectGenerator generator) {
55     myGenerator = generator;
56     myAvailableCourses = myGenerator.getCourses(false);
57     myBrowseButton.setPreferredSize(new Dimension(28, 28));
58     myRefreshButton.setPreferredSize(new Dimension(28, 28));
59     if (myAvailableCourses.isEmpty()) {
60       setError(CONNECTION_ERROR);
61     }
62     else {
63       for (CourseInfo courseInfo : myAvailableCourses) {
64         myCoursesComboBox.addItem(courseInfo);
65       }
66       final CourseInfo selectedCourse = StudyUtils.getFirst(myAvailableCourses);
67       final String authorsString = Course.getAuthorsString(selectedCourse.getAuthors());
68       myAuthorLabel.setText(!StringUtil.isEmptyOrSpaces(authorsString) ? "Author: " + authorsString : "");
69       myDescriptionLabel.setText(selectedCourse.getDescription());
70       myDescriptionLabel.setEditable(false);
71       //setting the first course in list as selected
72       myGenerator.setSelectedCourse(selectedCourse);
73       setOK();
74     }
75     initListeners();
76     myRefreshButton.setVisible(true);
77     myRefreshButton.putClientProperty("JButton.buttonType", "null");
78     myRefreshButton.setIcon(AllIcons.Actions.Refresh);
79
80     myLabel.setPreferredSize(new JLabel("Project name").getPreferredSize());
81
82   }
83
84   private void setupBrowseButton() {
85     myBrowseButton.putClientProperty("JButton.buttonType", "null");
86     myBrowseButton.setIcon(InteractiveLearningIcons.InterpreterGear);
87     final FileChooserDescriptor fileChooser = new FileChooserDescriptor(true, false, false, true, false, false) {
88       @Override
89       public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
90         return file.isDirectory() || StudyUtils.isZip(file.getName());
91       }
92
93       @Override
94       public boolean isFileSelectable(VirtualFile file) {
95         return StudyUtils.isZip(file.getName());
96       }
97     };
98     myBrowseButton.addActionListener(new ActionListener() {
99       public void actionPerformed(ActionEvent e) {
100         final BaseListPopupStep<String> popupStep = new BaseListPopupStep<String>("", "Add local course", "Load private courses") {
101           @Override
102           public PopupStep onChosen(final String selectedValue, boolean finalChoice) {
103             return doFinalStep(new Runnable() {
104               public void run() {
105                 if ("Add local course".equals(selectedValue)) {
106
107                   Project[] projects = ProjectManager.getInstance().getOpenProjects();
108                   FileChooser.chooseFile(fileChooser, null, projects.length == 0 ? null : projects[0].getBaseDir(),
109                                          new Consumer<VirtualFile>() {
110                                            @Override
111                                            public void consume(VirtualFile file) {
112                                              String fileName = file.getPath();
113                                              int oldSize = myAvailableCourses.size();
114                                              CourseInfo courseInfo = myGenerator.addLocalCourse(fileName);
115                                              if (courseInfo != null) {
116                                                if (oldSize != myAvailableCourses.size()) {
117                                                  myCoursesComboBox.addItem(courseInfo);
118                                                }
119                                                myCoursesComboBox.setSelectedItem(courseInfo);
120                                                setOK();
121                                              }
122                                              else {
123                                                setError(INVALID_COURSE);
124                                                myCoursesComboBox.removeAllItems();
125                                                myCoursesComboBox.addItem(CourseInfo.INVALID_COURSE);
126                                                for (CourseInfo course : myAvailableCourses) {
127                                                  myCoursesComboBox.addItem(course);
128                                                }
129                                                myCoursesComboBox.setSelectedItem(CourseInfo.INVALID_COURSE);
130                                              }
131                                            }
132                                          });
133                 }
134                 else if ("Load private courses".equals(selectedValue)) {
135                   final AddRemoteDialog dialog = new AddRemoteDialog();
136                   dialog.show();
137                 }
138               }
139             });
140           }
141         };
142         final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep);
143         popup.showInScreenCoordinates(myBrowseButton, myBrowseButton.getLocationOnScreen());
144       }
145     });
146   }
147
148   private void initListeners() {
149     myRefreshButton.addActionListener(new RefreshActionListener());
150     myCoursesComboBox.addActionListener(new CourseSelectedListener());
151     setupBrowseButton();
152   }
153
154   private void setError(@NotNull final String errorMessage) {
155     myGenerator.fireStateChanged(new ValidationResult(errorMessage));
156     if (myValidationManager != null) {
157       myValidationManager.validate();
158     }
159   }
160
161   private void setOK() {
162     myGenerator.fireStateChanged(ValidationResult.OK);
163     if (myValidationManager != null) {
164       myValidationManager.validate();
165     }
166   }
167
168   public JPanel getContentPanel() {
169     return myContentPanel;
170   }
171
172   public void registerValidators(final FacetValidatorsManager manager) {
173     myValidationManager = manager;
174   }
175
176
177   /**
178    * Handles refreshing courses
179    * Old courses added to new courses only if their
180    * meta file still exists in local file system
181    */
182   private class RefreshActionListener implements ActionListener {
183     @Override
184     public void actionPerformed(ActionEvent e) {
185       refreshCoursesList();
186     }
187   }
188
189   private void refreshCoursesList() {
190     final List<CourseInfo> courses = myGenerator.getCourses(true);
191     if (courses.isEmpty()) {
192       setError(CONNECTION_ERROR);
193       return;
194     }
195     myCoursesComboBox.removeAllItems();
196
197     for (CourseInfo courseInfo : courses) {
198       myCoursesComboBox.addItem(courseInfo);
199     }
200     myGenerator.setSelectedCourse(StudyUtils.getFirst(courses));
201
202     myGenerator.setCourses(courses);
203     myAvailableCourses = courses;
204     StudyProjectGenerator.flushCache(myAvailableCourses);
205   }
206
207
208   /**
209    * Handles selecting course in combo box
210    * Sets selected course in combo box as selected in
211    * {@link StudyNewProjectPanel#myGenerator}
212    */
213   private class CourseSelectedListener implements ActionListener {
214     @Override
215     public void actionPerformed(ActionEvent e) {
216       JComboBox cb = (JComboBox)e.getSource();
217       CourseInfo selectedCourse = (CourseInfo)cb.getSelectedItem();
218       if (selectedCourse == null || selectedCourse.equals(CourseInfo.INVALID_COURSE)) {
219         myAuthorLabel.setText("");
220         myDescriptionLabel.setText("");
221         return;
222       }
223       final String authorsString = Course.getAuthorsString(selectedCourse.getAuthors());
224       myAuthorLabel.setText(!StringUtil.isEmptyOrSpaces(authorsString) ?"Author: " + authorsString : "");
225       myCoursesComboBox.removeItem(CourseInfo.INVALID_COURSE);
226       myDescriptionLabel.setText(selectedCourse.getDescription());
227       myGenerator.setSelectedCourse(selectedCourse);
228       setOK();
229     }
230   }
231
232   public JComboBox getCoursesComboBox() {
233     return myCoursesComboBox;
234   }
235
236   public JPanel getInfoPanel() {
237     return myInfoPanel;
238   }
239
240   private class AddRemoteDialog extends DialogWrapper {
241
242     private final StudyAddRemoteCourse myRemoteCourse;
243
244     protected AddRemoteDialog() {
245       super(null);
246       myRemoteCourse = new StudyAddRemoteCourse();
247       init();
248     }
249
250     @Nullable
251     @Override
252     protected JComponent createCenterPanel() {
253       return myRemoteCourse.getContentPanel();
254     }
255
256     @Override
257     protected void doOKAction() {
258       if (StringUtil.isEmptyOrSpaces(myRemoteCourse.getLogin())) {
259         myRemoteCourse.setError("Please, enter your login");
260         return;
261       }
262       if (StringUtil.isEmptyOrSpaces(myRemoteCourse.getPassword())) {
263         myRemoteCourse.setError("Please, enter your password");
264         return;
265       }
266
267       super.doOKAction();
268       final boolean isSuccess = EduStepicConnector.login(myRemoteCourse.getLogin(), myRemoteCourse.getPassword());
269       if (!isSuccess) {
270         setError("Failed to log in");
271       }
272       StudySettings.getInstance().setLogin(myRemoteCourse.getLogin());
273       StudySettings.getInstance().setPassword(myRemoteCourse.getPassword());
274       refreshCoursesList();
275     }
276   }
277
278 }