new editing mode for task description panel
[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     else {
101       LOG.warn("No StudyPluginConfigurator is provided for the plugin");
102     }
103   }
104
105   public void dispose() {
106   }
107
108   //used in checkiO plugin.
109   @SuppressWarnings("unused")
110   public void showPanelById(@NotNull final String panelId) {
111     myCardLayout.swipe(myContentPanel, panelId, JBCardLayout.SwipeDirection.AUTO);
112   }
113
114   //used in checkiO plugin.
115   @SuppressWarnings("unused")
116   public void setBottomComponent(JComponent component) {
117     mySplitPane.setSecondComponent(component);
118   }
119
120   //used in checkiO plugin.
121   @SuppressWarnings("unused")
122   public JComponent getBottomComponent() {
123     return mySplitPane.getSecondComponent();
124   }
125
126   //used in checkiO plugin.
127   @SuppressWarnings("unused")
128   public void setTopComponentPrefferedSize(@NotNull final Dimension dimension) {
129     myContentPanel.setPreferredSize(dimension);
130   }
131
132   //used in checkiO plugin.
133   @SuppressWarnings("unused")
134   public JPanel getContentPanel() {
135     return myContentPanel;
136   }
137
138
139   public abstract JComponent createTaskInfoPanel(Project project);
140
141   public static JPanel createToolbarPanel(ActionGroup group) {
142     final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar("Study", group, true);
143     return JBUI.Panels.simplePanel(actionToolBar.getComponent());
144   }
145
146   public static DefaultActionGroup getActionGroup(@NotNull final Project project) {
147     DefaultActionGroup group = new DefaultActionGroup();
148     Course course = StudyTaskManager.getInstance(project).getCourse();
149     if (course == null) {
150       LOG.warn("Course is null");
151       return group;
152     }
153     StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project);
154     if (configurator != null) {
155       group.addAll(configurator.getActionGroup(project));
156       addAdditionalActions(group);
157       return group;
158     }
159     else {
160       LOG.warn("No configurator is provided for plugin");
161       return StudyBasePluginConfigurator.getDefaultActionGroup();
162     }
163   }
164
165   private static void addAdditionalActions(DefaultActionGroup group) {
166     StudyActionsProvider[] providers = Extensions.getExtensions(StudyActionsProvider.EP_NAME);
167     for (StudyActionsProvider provider : providers) {
168       group.addAll(provider.getActions());
169     }
170   }
171
172   public void setTaskText(String text, VirtualFile taskDirectory, Project project) {
173     if (StudyTaskManager.getInstance(project).isTurnEditingMode()) {
174       if (taskDirectory == null) {
175         LOG.info("Failed to enter editing mode for StudyToolWindow");
176         return;
177       }
178       VirtualFile taskTextFile = taskDirectory.findChild(EduNames.TASK_HTML);
179       enterEditingMode(taskTextFile, project);
180       StudyTaskManager.getInstance(project).setTurnEditingMode(false);
181     }
182     else {
183       setText(text);
184     }
185   }
186
187   protected abstract void setText(String text);
188
189   public void setEmptyText(@NotNull Project project) {
190     if (StudyTaskManager.getInstance(project).getToolWindowMode() == StudyToolWindowMode.EDITING) {
191       mySplitPane.setFirstComponent(myContentPanel);
192       StudyTaskManager.getInstance(project).setTurnEditingMode(true);
193     }
194     setTaskText(EMPTY_TASK_TEXT, null, project);
195   }
196
197   public enum StudyToolWindowMode {
198     TEXT, EDITING
199   }
200
201
202   public void enterEditingMode(VirtualFile taskFile, Project project) {
203     final EditorFactory factory = EditorFactory.getInstance();
204     Document document = FileDocumentManager.getInstance().getDocument(taskFile);
205     if (document == null) {
206       return;
207     }
208     WebBrowserManager.getInstance().setShowBrowserHover(false);
209     final EditorEx createdEditor = (EditorEx)factory.createEditor(document, project, taskFile, false);
210     Disposer.register(project, new Disposable() {
211       public void dispose() {
212         factory.releaseEditor(createdEditor);
213       }
214     });
215     JComponent editorComponent = createdEditor.getComponent();
216     mySplitPane.setFirstComponent(editorComponent);
217     mySplitPane.repaint();
218
219     StudyTaskManager.getInstance(project).setToolWindowMode(StudyToolWindowMode.EDITING);
220   }
221
222
223   public void leaveEditingMode(Project project) {
224     WebBrowserManager.getInstance().setShowBrowserHover(true);
225     mySplitPane.setFirstComponent(myContentPanel);
226     StudyTaskManager.getInstance(project).setToolWindowMode(StudyToolWindowMode.TEXT);
227     StudyUtils.updateStudyToolWindow(project);
228   }
229 }