a060a8d690628a81ee5027a4e02b270d18fc82b7
[idea/community.git] / python / educational / interactive-learning / src / com / jetbrains / edu / learning / ui / StudyToolWindow.java
1 /*
2  * Copyright 2000-2015 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.jetbrains.edu.learning.ui;
17
18 import com.intellij.openapi.Disposable;
19 import com.intellij.openapi.actionSystem.ActionManager;
20 import com.intellij.openapi.actionSystem.ActionToolbar;
21 import com.intellij.openapi.actionSystem.DataProvider;
22 import com.intellij.openapi.actionSystem.DefaultActionGroup;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.editor.colors.EditorColorsManager;
25 import com.intellij.openapi.editor.colors.EditorColorsScheme;
26 import com.intellij.openapi.fileEditor.FileEditorManager;
27 import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
28 import com.intellij.openapi.fileEditor.FileEditorManagerListener;
29 import com.intellij.openapi.project.Project;
30 import com.intellij.openapi.ui.SimpleToolWindowPanel;
31 import com.intellij.openapi.util.io.FileUtil;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import com.intellij.ui.BrowserHyperlinkListener;
34 import com.intellij.ui.components.JBScrollPane;
35 import com.intellij.util.ui.JBUI;
36 import com.intellij.util.ui.UIUtil;
37 import com.jetbrains.edu.EduNames;
38 import com.jetbrains.edu.courseFormat.Task;
39 import com.jetbrains.edu.courseFormat.TaskFile;
40 import com.jetbrains.edu.learning.StudyUtils;
41 import com.jetbrains.edu.learning.actions.*;
42 import com.jetbrains.edu.learning.editor.StudyEditor;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
45
46 import javax.swing.*;
47 import javax.swing.border.EmptyBorder;
48 import javax.swing.text.html.HTMLDocument;
49 import javax.swing.text.html.HTMLEditorKit;
50 import java.awt.*;
51 import java.io.IOException;
52
53 public class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable {
54
55   private static final String EMPTY_TASK_TEXT = "Please, open any task to see task description";
56
57   public StudyToolWindow(final Project project) {
58     super(true, true);
59     JPanel toolbarPanel = createToolbarPanel();
60     setToolbar(toolbarPanel);
61
62     final StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
63     final JTextPane taskTextPane = createTaskTextPane();
64
65     if (studyEditor == null) {
66       taskTextPane.setText(EMPTY_TASK_TEXT);
67       setContent(taskTextPane);
68       return;
69     }
70     final Task task = studyEditor.getTaskFile().getTask();
71
72     if (task != null) {
73       final String taskText = task.getText();
74       JBScrollPane scrollPane = new JBScrollPane(taskTextPane);
75       taskTextPane.setText(taskText);
76       taskTextPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE);
77
78       setContent(scrollPane);
79
80       final FileEditorManagerListener listener = new StudyFileEditorManagerListener(project, taskTextPane);
81       project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, listener);
82     }
83   }
84
85   @NotNull
86   private JTextPane createTaskTextPane() {
87     final JTextPane taskTextPane = new JTextPane();
88     taskTextPane.setContentType(new HTMLEditorKit().getContentType());
89     final EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
90     int fontSize = editorColorsScheme.getEditorFontSize();
91     final String fontName = editorColorsScheme.getEditorFontName();
92     final Font font = new Font(fontName, Font.PLAIN, fontSize);
93     String bodyRule = "body { font-family: " + font.getFamily() + "; " +
94                       "font-size: " + font.getSize() + "pt; }";
95     ((HTMLDocument)taskTextPane.getDocument()).getStyleSheet().addRule(bodyRule);
96     taskTextPane.setEditable(false);
97     if (!UIUtil.isUnderDarcula()) {
98       taskTextPane.setBackground(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground());
99     }
100     taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100));
101     return taskTextPane;
102   }
103
104   public void dispose() {
105   }
106
107   private static JPanel createToolbarPanel() {
108     final DefaultActionGroup group = new DefaultActionGroup();
109     group.add(new StudyCheckAction());
110     group.add(new StudyPreviousStudyTaskAction());
111     group.add(new StudyNextStudyTaskAction());
112     group.add(new StudyRefreshTaskFileAction());
113     group.add(new StudyShowHintAction());
114
115     group.add(new StudyRunAction());
116     group.add(new StudyEditInputAction());
117
118     final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar("Study", group, true);
119     return JBUI.Panels.simplePanel(actionToolBar.getComponent());
120   }
121
122   static class StudyFileEditorManagerListener implements FileEditorManagerListener {
123     private static final Logger LOG = Logger.getInstance(StudyFileEditorManagerListener.class);
124     private Project myProject;
125     private JTextPane myTaskTextPane;
126
127     StudyFileEditorManagerListener(@NotNull final Project project, JTextPane taskTextPane) {
128       myProject = project;
129       myTaskTextPane = taskTextPane;
130     }
131
132     @Override
133     public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
134       Task task = getTask(file);
135       setTaskText(task, file.getParent());
136     }
137
138     @Override
139     public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
140       myTaskTextPane.setText(EMPTY_TASK_TEXT);
141     }
142
143     @Override
144     public void selectionChanged(@NotNull FileEditorManagerEvent event) {
145       VirtualFile file = event.getNewFile();
146       if (file != null) {
147         Task task = getTask(file);
148         setTaskText(task, file);
149       }
150     }
151
152     @Nullable
153     private Task getTask(@NotNull VirtualFile file) {
154       TaskFile taskFile = StudyUtils.getTaskFile(myProject, file);
155       if (taskFile != null) {
156         return taskFile.getTask();
157       }
158       else {
159         return null;
160       }
161     }
162
163     private void setTaskText(@Nullable final Task task, @Nullable final VirtualFile taskDirectory) {
164       if (task == null) {
165         myTaskTextPane.setText(EMPTY_TASK_TEXT);
166         return;
167       }
168       String text = task.getText();
169       if (text == null && taskDirectory != null) {
170         VirtualFile taskTextFile = taskDirectory.findChild(EduNames.TASK_HTML);
171         if (taskTextFile != null) {
172           try {
173             text = FileUtil.loadTextAndClose(taskTextFile.getInputStream());
174           }
175           catch (IOException e) {
176             LOG.info(e);
177           }
178         }
179       }
180       myTaskTextPane.setText(text);
181     }
182   }
183 }