Show content without code highlighting if configurator wasn't found
[idea/community.git] / python / educational-core / student / 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.ide.browsers.WebBrowserManager;
19 import com.intellij.openapi.Disposable;
20 import com.intellij.openapi.actionSystem.*;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.editor.Document;
23 import com.intellij.openapi.editor.EditorFactory;
24 import com.intellij.openapi.editor.ex.EditorEx;
25 import com.intellij.openapi.extensions.Extensions;
26 import com.intellij.openapi.fileEditor.FileDocumentManager;
27 import com.intellij.openapi.fileEditor.FileEditorManagerListener;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.ui.SimpleToolWindowPanel;
30 import com.intellij.openapi.util.Disposer;
31 import com.intellij.openapi.vfs.VirtualFile;
32 import com.intellij.ui.JBCardLayout;
33 import com.intellij.ui.OnePixelSplitter;
34 import com.intellij.util.ui.JBUI;
35 import com.jetbrains.edu.learning.*;
36 import com.jetbrains.edu.learning.core.EduNames;
37 import com.jetbrains.edu.learning.courseFormat.Course;
38 import com.jetbrains.edu.learning.courseFormat.TaskFile;
39 import org.jetbrains.annotations.NotNull;
40
41 import javax.swing.*;
42 import java.awt.*;
43 import java.util.Map;
44
45 public abstract class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable {
46   private static final Logger LOG = Logger.getInstance(StudyToolWindow.class);
47   private static final String TASK_INFO_ID = "taskInfo";
48   private static final String EMPTY_TASK_TEXT = "Please, open any task to see task description";
49   private final JBCardLayout myCardLayout;
50   private final JPanel myContentPanel;
51   private final OnePixelSplitter mySplitPane;
52
53   public StudyToolWindow() {
54     super(true, true);
55     myCardLayout = new JBCardLayout();
56     myContentPanel = new JPanel(myCardLayout);
57     mySplitPane = new OnePixelSplitter(myVertical = true);
58   }
59
60   public void init(Project project) {
61     String taskText = StudyUtils.getTaskText(project);
62     if (taskText == null) return;
63
64     JPanel toolbarPanel = createToolbarPanel(getActionGroup(project));
65     setToolbar(toolbarPanel);
66
67     myContentPanel.add(TASK_INFO_ID, createTaskInfoPanel(project));
68     mySplitPane.setFirstComponent(myContentPanel);
69     addAdditionalPanels(project);
70     myCardLayout.show(myContentPanel, TASK_INFO_ID);
71
72     setContent(mySplitPane);
73
74     StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
75     if (configurator != null) {
76       final FileEditorManagerListener listener = configurator.getFileEditorManagerListener(project, this);
77       project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, listener);
78     }
79
80     if (StudyTaskManager.getInstance(project).isTurnEditingMode() || StudyTaskManager.getInstance(project).getToolWindowMode() == StudyToolWindowMode.EDITING) {
81       TaskFile file = StudyUtils.getSelectedTaskFile(project);
82       if (file != null) {
83         VirtualFile taskDir = file.getTask().getTaskDir(project);
84         setTaskText(taskText, taskDir, project);
85
86       }
87     } else {
88       setTaskText(taskText, null, project);
89     }
90   }
91
92   private void addAdditionalPanels(Project project) {
93     StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
94     if (configurator != null) {
95       Map<String, JPanel> panels = configurator.getAdditionalPanels(project);
96       for (Map.Entry<String, JPanel> entry : panels.entrySet()) {
97         myContentPanel.add(entry.getKey(), entry.getValue());
98       }
99     }
100   }
101
102   public void dispose() {
103   }
104
105   //used in checkiO plugin.
106   @SuppressWarnings("unused")
107   public void showPanelById(@NotNull final String panelId) {
108     myCardLayout.swipe(myContentPanel, panelId, JBCardLayout.SwipeDirection.AUTO);
109   }
110
111   //used in checkiO plugin.
112   @SuppressWarnings("unused")
113   public void setBottomComponent(JComponent component) {
114     mySplitPane.setSecondComponent(component);
115   }
116
117   //used in checkiO plugin.
118   @SuppressWarnings("unused")
119   public JComponent getBottomComponent() {
120     return mySplitPane.getSecondComponent();
121   }
122
123   //used in checkiO plugin.
124   @SuppressWarnings("unused")
125   public void setTopComponentPrefferedSize(@NotNull final Dimension dimension) {
126     myContentPanel.setPreferredSize(dimension);
127   }
128
129   //used in checkiO plugin.
130   @SuppressWarnings("unused")
131   public JPanel getContentPanel() {
132     return myContentPanel;
133   }
134
135
136   public abstract JComponent createTaskInfoPanel(Project project);
137
138   public static JPanel createToolbarPanel(ActionGroup group) {
139     final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar("Study", group, true);
140     return JBUI.Panels.simplePanel(actionToolBar.getComponent());
141   }
142
143   public static DefaultActionGroup getActionGroup(@NotNull final Project project) {
144     DefaultActionGroup group = new DefaultActionGroup();
145     Course course = StudyTaskManager.getInstance(project).getCourse();
146     if (course == null) {
147       LOG.warn("Course is null");
148       return group;
149     }
150     StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
151     if (configurator != null) {
152       group.addAll(configurator.getActionGroup(project));
153       addAdditionalActions(group);
154       return group;
155     }
156     else {
157       LOG.warn("No configurator is provided for plugin");
158       return StudyBasePluginConfigurator.getDefaultActionGroup();
159     }
160   }
161
162   private static void addAdditionalActions(DefaultActionGroup group) {
163     StudyActionsProvider[] providers = Extensions.getExtensions(StudyActionsProvider.EP_NAME);
164     for (StudyActionsProvider provider : providers) {
165       group.addAll(provider.getActions());
166     }
167   }
168
169   public void setTaskText(String text, VirtualFile taskDirectory, Project project) {
170     if (StudyTaskManager.getInstance(project).isTurnEditingMode()) {
171       if (taskDirectory == null) {
172         LOG.info("Failed to enter editing mode for StudyToolWindow");
173         return;
174       }
175       VirtualFile taskTextFile = taskDirectory.findChild(EduNames.TASK_HTML);
176       enterEditingMode(taskTextFile, project);
177       StudyTaskManager.getInstance(project).setTurnEditingMode(false);
178     }
179     else {
180       setText(text);
181     }
182   }
183
184   protected abstract void setText(String text);
185
186   public void setEmptyText(@NotNull Project project) {
187     if (StudyTaskManager.getInstance(project).getToolWindowMode() == StudyToolWindowMode.EDITING) {
188       mySplitPane.setFirstComponent(myContentPanel);
189       StudyTaskManager.getInstance(project).setTurnEditingMode(true);
190     }
191     setTaskText(EMPTY_TASK_TEXT, null, project);
192   }
193
194   public enum StudyToolWindowMode {
195     TEXT, EDITING
196   }
197
198
199   public void enterEditingMode(VirtualFile taskFile, Project project) {
200     final EditorFactory factory = EditorFactory.getInstance();
201     Document document = FileDocumentManager.getInstance().getDocument(taskFile);
202     if (document == null) {
203       return;
204     }
205     WebBrowserManager.getInstance().setShowBrowserHover(false);
206     final EditorEx createdEditor = (EditorEx)factory.createEditor(document, project, taskFile, false);
207     Disposer.register(project, new Disposable() {
208       public void dispose() {
209         factory.releaseEditor(createdEditor);
210       }
211     });
212     JComponent editorComponent = createdEditor.getComponent();
213     mySplitPane.setFirstComponent(editorComponent);
214     mySplitPane.repaint();
215
216     StudyTaskManager.getInstance(project).setToolWindowMode(StudyToolWindowMode.EDITING);
217   }
218
219
220   public void leaveEditingMode(Project project) {
221     WebBrowserManager.getInstance().setShowBrowserHover(true);
222     mySplitPane.setFirstComponent(myContentPanel);
223     StudyTaskManager.getInstance(project).setToolWindowMode(StudyToolWindowMode.TEXT);
224     StudyUtils.updateStudyToolWindow(project);
225   }
226 }