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