a9634d5a335acf0d8372a9cd29f78fbf6398bec4
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / fileEditor / impl / PreviewPanel.java
1 /*
2  * Copyright 2000-2014 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.intellij.openapi.fileEditor.impl;
17
18 import com.intellij.icons.AllIcons;
19 import com.intellij.ide.ui.UISettings;
20 import com.intellij.openapi.actionSystem.AnAction;
21 import com.intellij.openapi.actionSystem.AnActionEvent;
22 import com.intellij.openapi.editor.Document;
23 import com.intellij.openapi.editor.event.DocumentEvent;
24 import com.intellij.openapi.editor.event.DocumentListener;
25 import com.intellij.openapi.fileEditor.FileDocumentManager;
26 import com.intellij.openapi.fileEditor.FileEditorManager;
27 import com.intellij.openapi.fileEditor.FileEditorManagerListener;
28 import com.intellij.openapi.project.Project;
29 import com.intellij.openapi.util.text.StringUtil;
30 import com.intellij.openapi.vfs.VirtualFile;
31 import com.intellij.openapi.wm.ToolWindowAnchor;
32 import com.intellij.openapi.wm.ToolWindowId;
33 import com.intellij.openapi.wm.ToolWindowManager;
34 import com.intellij.openapi.wm.impl.ToolWindowImpl;
35 import com.intellij.ui.JBColor;
36 import com.intellij.ui.docking.DockManager;
37 import org.jetbrains.annotations.NotNull;
38 import org.jetbrains.annotations.Nullable;
39
40 import javax.swing.*;
41 import java.awt.*;
42 import java.util.ArrayList;
43
44 class PreviewPanel extends JPanel implements DocumentListener, FileEditorManagerListener.Before {
45   private static final int HISTORY_LIMIT = 10;
46
47   private final Project myProject;
48   private final FileEditorManagerImpl myManager;
49   private final DockManager myDockManager;
50   private EditorWindow myWindow;
51   private boolean myInitialized = false;
52   private EditorsSplitters myEditorsSplitters;
53   private ArrayList<VirtualFile> myHistory = new ArrayList<VirtualFile>();
54   private VirtualFile myModifiedFile = null;
55   private ToolWindowImpl myToolWindow;
56   private VirtualFile myAwaitingForOpen = null;
57
58   public PreviewPanel(Project project, FileEditorManagerImpl manager, DockManager dockManager) {
59     myProject = project;
60     myManager = manager;
61     myDockManager = dockManager;
62     setOpaque(true);
63     setBackground(JBColor.DARK_GRAY);
64   }
65
66   private void initToolWindowIfNeed() {
67     if (myInitialized) return;
68
69     myToolWindow = (ToolWindowImpl)ToolWindowManager.getInstance(myProject)
70       .registerToolWindow(ToolWindowId.PREVIEW, this, ToolWindowAnchor.RIGHT, myProject, false);
71     myToolWindow.setIcon(AllIcons.Actions.PreviewDetails);
72
73     myEditorsSplitters = new EditorsSplitters(myManager, myDockManager, false) {
74       @Override
75       public void updateFileName(VirtualFile updatedFile) {
76         super.updateFileName(updatedFile);
77         if (updatedFile != null && updatedFile.equals(getCurrentFile())) {
78           updateWindowTitle(updatedFile);
79         }
80       }
81
82       @Override
83       protected void afterFileOpen(VirtualFile file) {
84         if (file.equals(myAwaitingForOpen)) {
85           updateWindowTitle(file);
86           Document document = FileDocumentManager.getInstance().getDocument(file);
87           if (document != null) {
88             myModifiedFile = null;
89             document.addDocumentListener(PreviewPanel.this, myProject);
90           }
91         }
92         myAwaitingForOpen = null;
93       }
94
95       @Override
96       public void setTabsPlacement(int tabPlacement) {
97         super.setTabsPlacement(UISettings.TABS_NONE);
98       }
99
100       @Override
101       protected boolean showEmptyText() {
102         return false;
103       }
104     };
105
106     myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER, this);
107     myEditorsSplitters.createCurrentWindow();
108
109     myWindow = myEditorsSplitters.getCurrentWindow();
110     myWindow.setTabsPlacement(UISettings.TABS_NONE);
111
112     setLayout(new GridLayout(1, 1));
113     add(myEditorsSplitters);
114
115     myToolWindow.setTitleActions(new MoveToEditorTabsAction(), new CloseFileAction());
116
117     myInitialized = true;
118   }
119
120   private void updateWindowTitle(VirtualFile file) {
121     if (myToolWindow == null) return;
122     if (file == null) {
123       myToolWindow.setTitle(": (empty)");
124     }
125     else {
126       myToolWindow.setTitle(": " +
127                             StringUtil.getShortened(EditorTabbedContainer.calcTabTitle(myProject, file),
128                                                     UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT));
129     }
130   }
131
132   @Override
133   public void beforeFileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
134     myAwaitingForOpen = file;
135   }
136
137   @Override
138   public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
139     if (file.equals(getCurrentFile())) {
140       updateWindowTitle(null);
141       Document document = FileDocumentManager.getInstance().getDocument(file);
142       if (document != null) {
143         document.removeDocumentListener(this);
144       }
145     }
146   }
147
148
149   @Override
150   public void beforeDocumentChange(DocumentEvent event) {
151
152   }
153
154   @Override
155   public void documentChanged(DocumentEvent event) {
156     VirtualFile file = FileDocumentManager.getInstance().getFile(event.getDocument());
157     if (file != null) {
158       myModifiedFile = file;
159     }
160   }
161
162   EditorWindow getWindow() {
163     initToolWindowIfNeed();
164     return myWindow;
165   }
166
167   @Nullable
168   VirtualFile getCurrentFile() {
169     VirtualFile[] files = myWindow.getFiles();
170     return files.length == 1 ? files[0] : null;
171   }
172
173   private class MoveToEditorTabsAction extends AnAction {
174     public MoveToEditorTabsAction() {
175       super(null, "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed);
176     }
177
178     @Override
179     public void actionPerformed(AnActionEvent e) {
180       VirtualFile virtualFile = getCurrentFile();
181       if (virtualFile == null) {
182         return;
183       }
184
185       myManager.openFileWithProviders(virtualFile, false, myManager.getCurrentWindow());
186       closeCurrentFile();
187     }
188
189     @Override
190     public void update(AnActionEvent e) {
191       super.update(e);
192       VirtualFile currentFile = getCurrentFile();
193       e.getPresentation().setEnabled(currentFile != null);
194       if (currentFile == null) return;
195
196       if (isModified(currentFile)) {
197         e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeft);
198       }
199       else {
200         e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeftGrayed);
201       }
202     }
203   }
204
205   private boolean isModified(@NotNull VirtualFile file) {
206     return file.equals(myModifiedFile);
207   }
208
209   //returns last open file if it has "modified" status
210   @Nullable
211   VirtualFile closeCurrentFile() {
212     VirtualFile virtualFile = getCurrentFile();
213     if (virtualFile == null) return null;
214     if (!myHistory.contains(virtualFile)) {
215       myHistory.add(virtualFile);
216       while (myHistory.size() > HISTORY_LIMIT) {
217         myHistory.remove(0);
218       }
219     }
220     myWindow.closeFile(virtualFile);
221     this.revalidate();
222     this.repaint();
223     return isModified(virtualFile) ? virtualFile : null;
224   }
225
226   private class CloseFileAction extends AnAction {
227     public CloseFileAction() {
228       super(null, "Close", AllIcons.Actions.Close);
229     }
230
231     @Override
232     public void actionPerformed(AnActionEvent e) {
233       if (getCurrentFile() == null) return;
234       closeCurrentFile();
235       ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).hide(null);
236     }
237
238     @Override
239     public void update(AnActionEvent e) {
240       super.update(e);
241       e.getPresentation().setEnabled(getCurrentFile() != null);
242     }
243   }
244 }