3 * Copyright 2000-2009 JetBrains s.r.o.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package com
.intellij
.ide
.actions
;
19 import com
.intellij
.openapi
.actionSystem
.*;
20 import com
.intellij
.openapi
.editor
.markup
.EffectType
;
21 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
22 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
23 import com
.intellij
.openapi
.fileEditor
.ex
.FileEditorProviderManager
;
24 import com
.intellij
.openapi
.fileEditor
.impl
.EditorHistoryManager
;
25 import com
.intellij
.openapi
.keymap
.KeymapManager
;
26 import com
.intellij
.openapi
.project
.DumbAware
;
27 import com
.intellij
.openapi
.project
.Project
;
28 import com
.intellij
.openapi
.ui
.popup
.PopupChooserBuilder
;
29 import com
.intellij
.openapi
.util
.Iconable
;
30 import com
.intellij
.openapi
.vcs
.FileStatus
;
31 import com
.intellij
.openapi
.vcs
.FileStatusManager
;
32 import com
.intellij
.openapi
.vfs
.VirtualFile
;
33 import com
.intellij
.ui
.ColoredListCellRenderer
;
34 import com
.intellij
.ui
.LightColors
;
35 import com
.intellij
.ui
.SimpleTextAttributes
;
36 import com
.intellij
.util
.ArrayUtil
;
37 import com
.intellij
.util
.Function
;
38 import com
.intellij
.util
.IconUtil
;
41 import javax
.swing
.event
.ListSelectionEvent
;
42 import javax
.swing
.event
.ListSelectionListener
;
44 import java
.awt
.event
.KeyAdapter
;
45 import java
.awt
.event
.KeyEvent
;
48 public abstract class BaseShowRecentFilesAction
extends AnAction
implements DumbAware
{
49 private static final Color BORDER_COLOR
= new Color(0x87, 0x87, 0x87);
51 public void actionPerformed(AnActionEvent e
) {
52 show(PlatformDataKeys
.PROJECT
.getData(e
.getDataContext()));
55 public void update(AnActionEvent event
){
56 Presentation presentation
= event
.getPresentation();
57 Project project
= PlatformDataKeys
.PROJECT
.getData(event
.getDataContext());
58 presentation
.setEnabled(project
!= null);
61 private void show(final Project project
){
62 final DefaultListModel model
= new DefaultListModel();
64 VirtualFile
[] selectedFiles
= FileEditorManager
.getInstance(project
).getSelectedFiles();
65 VirtualFile
[] files
= filesToShow(project
);
66 FileEditorProviderManager editorProviderManager
= FileEditorProviderManager
.getInstance();
68 for(int i
=files
.length
-1; i
>= 0; i
--){ // reverse order of files
69 VirtualFile file
= files
[i
];
70 if(ArrayUtil
.find(selectedFiles
, file
) == -1 && editorProviderManager
.getProviders(project
, file
).length
> 0){
71 // 1. do not put currently selected file
72 // 2. do not include file with no corresponding editor providers
73 model
.addElement(file
);
77 final JLabel pathLabel
= new JLabel(" ");
78 pathLabel
.setHorizontalAlignment(SwingConstants
.RIGHT
);
80 if (true /*SystemInfo.isMac*/) {
81 final Font font
= pathLabel
.getFont();
82 pathLabel
.setFont(font
.deriveFont((float)10));
85 final JList list
= new JList(model
);
88 public void keyPressed(KeyEvent e
) {
89 if (e
.getKeyCode() == KeyEvent
.VK_DELETE
) {
90 int index
= list
.getSelectedIndex();
91 if (index
== -1 || index
>= list
.getModel().getSize()){
94 Object
[] values
= list
.getSelectedValues();
95 for (Object value
: values
) {
96 VirtualFile file
= (VirtualFile
) value
;
97 model
.removeElement(file
);
98 if (model
.getSize() > 0) {
99 if (model
.getSize() == index
) {
100 list
.setSelectedIndex(model
.getSize() - 1);
101 } else if (model
.getSize() > index
) {
102 list
.setSelectedIndex(index
);
105 list
.clearSelection();
107 EditorHistoryManager
.getInstance(project
).removeFile(file
);
114 list
.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
115 private String
getTitle2Text(String fullText
) {
116 int labelWidth
= pathLabel
.getWidth();
117 if (fullText
== null || fullText
.length() == 0) return " ";
118 while (pathLabel
.getFontMetrics(pathLabel
.getFont()).stringWidth(fullText
) > labelWidth
) {
119 int sep
= fullText
.indexOf(File
.separatorChar
, 4);
120 if (sep
< 0) return fullText
;
121 fullText
= "..." + fullText
.substring(sep
);
127 public void valueChanged(final ListSelectionEvent e
) {
128 //noinspection SSBasedInspection
129 SwingUtilities
.invokeLater(new Runnable() {
136 private void updatePathLabel() {
137 final Object
[] values
= list
.getSelectedValues();
138 if (values
!= null && values
.length
== 1) {
139 final VirtualFile parent
= ((VirtualFile
)values
[0]).getParent();
140 if (parent
!= null) {
141 pathLabel
.setText(getTitle2Text(parent
.getPresentableUrl()));
144 pathLabel
.setText(" ");
148 pathLabel
.setText(" ");
153 Runnable runnable
= new Runnable() {
155 Object
[] values
= list
.getSelectedValues();
156 for (Object value
: values
) {
157 VirtualFile file
= (VirtualFile
) value
;
158 FileEditorManager
.getInstance(project
).openFile(file
, true);
163 if (list
.getModel().getSize() == 0) {
164 list
.clearSelection();
167 list
.setCellRenderer(new RecentFilesRenderer(project
));
171 if (model.getSize() > 0) {
172 Dimension listPreferredSize = list.getPreferredSize();
173 list.setVisibleRowCount(0);
174 Dimension viewPreferredSize = new Dimension(listPreferredSize.width, Math.min(listPreferredSize.height, r.height - 20));
175 ((JViewport)list.getParent()).setPreferredSize(viewPreferredSize);
179 JPanel footerPanel
= new JPanel(new BorderLayout()) {
181 protected void paintComponent(Graphics g
) {
182 super.paintComponent(g
);
183 g
.setColor(BORDER_COLOR
);
184 g
.drawLine(0, 0, getWidth(), 0);
188 footerPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
189 footerPanel
.add(pathLabel
);
191 new PopupChooserBuilder(list
).
192 setTitle(getTitle()).
194 setSouthComponent(footerPanel
).
195 setItemChoosenCallback(runnable
).
196 addAdditionalChooseKeystroke(getAdditionalSelectKeystroke()).
197 setFilteringEnabled(new Function
<Object
, String
>() {
198 public String
fun(Object o
) {
199 return o
instanceof VirtualFile ?
((VirtualFile
)o
).getName() : "";
202 createPopup().showCenteredInCurrentWindow(project
);
205 protected abstract String
getTitle();
207 protected abstract VirtualFile
[] filesToShow(Project project
);
209 private static KeyStroke
getAdditionalSelectKeystroke() {
210 Shortcut
[] shortcuts
= KeymapManager
.getInstance().getActiveKeymap().getShortcuts(IdeActions
.ACTION_EDIT_SOURCE
);
211 for (Shortcut shortcut
: shortcuts
) {
212 if (shortcut
instanceof KeyboardShortcut
) {
213 return ((KeyboardShortcut
) shortcut
).getFirstKeyStroke();
219 private static class RecentFilesRenderer
extends ColoredListCellRenderer
{
220 private final Project myProject
;
221 public RecentFilesRenderer(Project project
) {
225 protected void customizeCellRenderer(JList list
, Object value
, int index
, boolean selected
, boolean hasFocus
) {
226 if (value
instanceof VirtualFile
) {
227 VirtualFile virtualFile
= (VirtualFile
)value
;
228 String name
= virtualFile
.getPresentableName();
229 setIcon(IconUtil
.getIcon(virtualFile
, Iconable
.ICON_FLAG_READ_STATUS
, myProject
));
231 FileStatus fileStatus
= FileStatusManager
.getInstance(myProject
).getStatus(virtualFile
);
232 TextAttributes attributes
= new TextAttributes(fileStatus
.getColor(), null , null, EffectType
.LINE_UNDERSCORE
,
234 append(name
, SimpleTextAttributes
.fromTextAttributes(attributes
));
236 if (!selected
&& FileEditorManager
.getInstance(myProject
).isFileOpen(virtualFile
)) {
237 setBackground(LightColors
.SLIGHTLY_GREEN
);