1 package com
.intellij
.ide
.util
.gotoByName
;
3 import com
.intellij
.ide
.DataManager
;
4 import com
.intellij
.ide
.IdeBundle
;
5 import com
.intellij
.ide
.util
.PropertiesComponent
;
6 import com
.intellij
.openapi
.actionSystem
.*;
7 import com
.intellij
.openapi
.actionSystem
.impl
.ActionManagerImpl
;
8 import com
.intellij
.openapi
.keymap
.KeymapManager
;
9 import com
.intellij
.openapi
.keymap
.KeymapUtil
;
10 import com
.intellij
.openapi
.project
.Project
;
11 import com
.intellij
.openapi
.util
.Comparing
;
12 import com
.intellij
.ui
.LayeredIcon
;
13 import com
.intellij
.util
.ui
.EmptyIcon
;
14 import com
.intellij
.util
.ui
.UIUtil
;
15 import com
.intellij
.util
.ArrayUtil
;
16 import org
.apache
.oro
.text
.regex
.*;
17 import org
.jetbrains
.annotations
.NonNls
;
18 import org
.jetbrains
.annotations
.NotNull
;
19 import org
.jetbrains
.annotations
.Nullable
;
25 public class GotoActionModel
implements ChooseByNameModel
, CustomMatcherModel
{
26 private final Project myProject
;
27 private final Component myContextComponent
;
29 private final ActionManager myActionManager
= ActionManager
.getInstance();
31 private static final EmptyIcon EMPTY_ICON
= new EmptyIcon(18, 18);
33 private String myPattern
;
35 private Pattern myCompiledPattern
;
36 private final PatternMatcher myMatcher
= new Perl5Matcher();
39 public GotoActionModel(Project project
, final Component component
) {
41 myContextComponent
= component
;
44 public String
getPromptText() {
45 return IdeBundle
.message("prompt.gotoaction.enter.action");
48 public String
getCheckBoxName() {
49 return IdeBundle
.message("checkbox.other.included");
52 public char getCheckBoxMnemonic() {
56 public String
getNotInMessage() {
57 return IdeBundle
.message("label.no.menu.actions.found");
60 public String
getNotFoundMessage() {
61 return IdeBundle
.message("label.no.actions.found");
64 public boolean loadInitialCheckBoxState() {
65 PropertiesComponent propertiesComponent
= PropertiesComponent
.getInstance(myProject
);
66 return propertiesComponent
.isTrueValue("GoToAction.allIncluded");
69 public void saveInitialCheckBoxState(boolean state
) {
70 PropertiesComponent propertiesComponent
= PropertiesComponent
.getInstance(myProject
);
71 propertiesComponent
.setValue("GoToAction.allIncluded", Boolean
.toString(state
));
74 public ListCellRenderer
getListCellRenderer() {
75 return new DefaultListCellRenderer() {
77 public Component
getListCellRendererComponent(final JList list
,
79 final int index
, final boolean isSelected
, final boolean cellHasFocus
) {
80 final JPanel panel
= new JPanel(new BorderLayout());
81 panel
.setOpaque(true);
82 final Color bg
= isSelected ? UIUtil
.getListSelectionBackground() : UIUtil
.getListBackground();
83 panel
.setBackground(bg
);
86 if (value
instanceof Map
.Entry
) {
88 final Map
.Entry actionWithParentGroup
= (Map
.Entry
)value
;
90 final AnAction anAction
= (AnAction
)actionWithParentGroup
.getKey();
91 final Presentation templatePresentation
= anAction
.getTemplatePresentation();
92 final Icon icon
= templatePresentation
.getIcon();
93 final LayeredIcon layeredIcon
= new LayeredIcon(2);
94 layeredIcon
.setIcon(EMPTY_ICON
, 0);
95 if (icon
!= null && icon
.getIconWidth() <= EMPTY_ICON
.getIconWidth() && icon
.getIconHeight() <= EMPTY_ICON
.getIconHeight()) {
96 layeredIcon
.setIcon(icon
, 1, (- icon
.getIconWidth() + EMPTY_ICON
.getIconWidth())/2, (EMPTY_ICON
.getIconHeight() - icon
.getIconHeight())/2);
99 final Presentation presentation
= new Presentation();
101 final AnActionEvent event
= new AnActionEvent(null, DataManager
.getInstance().getDataContext(myContextComponent
),
102 ActionPlaces
.UNKNOWN
, presentation
, ActionManager
.getInstance(),
104 anAction
.beforeActionPerformedUpdate(event
);
105 anAction
.update(event
);
107 final Color fg
= isSelected ? UIUtil
.getListSelectionForeground() :
108 presentation
.isEnabled() && presentation
.isVisible() ? UIUtil
.getListForeground() : UIUtil
.getInactiveTextColor();
110 final Shortcut
[] shortcutSet
= KeymapManager
.getInstance().getActiveKeymap().getShortcuts(myActionManager
.getId(anAction
));
111 final String actionPresentation
= templatePresentation
.getText() + (shortcutSet
!= null && shortcutSet
.length
> 0
112 ?
" (" + KeymapUtil
.getShortcutText(shortcutSet
[0]) + ")"
114 final JLabel actionLabel
= new JLabel(actionPresentation
, layeredIcon
, SwingConstants
.LEFT
);
115 actionLabel
.setBackground(bg
);
116 actionLabel
.setForeground(fg
);
118 panel
.add(actionLabel
, BorderLayout
.WEST
);
120 final String groupName
= (String
)actionWithParentGroup
.getValue();
121 if (groupName
!= null) {
122 final JLabel groupLabel
= new JLabel(groupName
);
123 groupLabel
.setBackground(bg
);
124 groupLabel
.setForeground(fg
);
125 panel
.add(groupLabel
, BorderLayout
.EAST
);
133 public String
[] getNames(boolean checkBoxState
) {
134 final ArrayList
<String
> result
= new ArrayList
<String
>();
135 collectActionIds(result
, (ActionGroup
)myActionManager
.getActionOrStub(IdeActions
.GROUP_MAIN_MENU
));
137 final Set
<String
> ids
= ((ActionManagerImpl
)myActionManager
).getActionIds();
138 for (String id
: ids
) {
139 final AnAction anAction
= myActionManager
.getAction(id
);
140 if (!(anAction
instanceof ActionGroup
)) {
145 return ArrayUtil
.toStringArray(result
);
148 private void collectActionIds(Collection
<String
> result
, ActionGroup group
){
149 final AnAction
[] actions
= group
.getChildren(null);
150 for (AnAction action
: actions
) {
151 if (action
instanceof ActionGroup
) {
152 collectActionIds(result
, (ActionGroup
)action
);
154 result
.add(myActionManager
.getId(action
));
159 public Object
[] getElementsByName(final String id
, final boolean checkBoxState
, final String pattern
) {
160 final HashMap
<AnAction
, String
> map
= new HashMap
<AnAction
, String
>();
161 final ActionGroup mainMenu
= (ActionGroup
)myActionManager
.getActionOrStub(IdeActions
.GROUP_MAIN_MENU
);
162 collectActions(id
, map
, mainMenu
, mainMenu
.getTemplatePresentation().getText());
164 final Set
<String
> ids
= ((ActionManagerImpl
)myActionManager
).getActionIds();
165 for (AnAction action
: map
.keySet()) { //do not add already included actions
166 ids
.remove(myActionManager
.getId(action
));
168 if (ids
.contains(id
)) {
169 final AnAction anAction
= myActionManager
.getAction(id
);
170 if (!(anAction
instanceof ActionGroup
)) {
171 map
.put(anAction
, null);
175 return map
.entrySet().toArray(new Map
.Entry
[map
.size()]);
178 private void collectActions(String id
, Map
<AnAction
, String
> result
, ActionGroup group
, final String containingGroupName
){
179 final AnAction
[] actions
= group
.getChildren(null);
180 for (AnAction action
: actions
) {
181 if (action
instanceof ActionGroup
) {
182 final ActionGroup actionGroup
= (ActionGroup
)action
;
183 final String groupName
= actionGroup
.getTemplatePresentation().getText();
184 collectActions(id
, result
, actionGroup
, groupName
!= null ? groupName
: containingGroupName
);
185 } else if (myActionManager
.getId(action
) == id
) {
186 final String groupName
= group
.getTemplatePresentation().getText();
187 result
.put(action
, groupName
!= null && groupName
.length() > 0 ? groupName
: containingGroupName
);
193 public String
getFullName(final Object element
) {
194 return getElementName(element
);
198 public String
[] getSeparators() {
199 return ArrayUtil
.EMPTY_STRING_ARRAY
;
202 public String
getElementName(final Object element
) {
203 if (!(element
instanceof Map
.Entry
)) return null;
204 return ((AnAction
)((Map
.Entry
)element
).getKey()).getTemplatePresentation().getText();
207 public boolean matches(@NotNull final String name
, @NotNull final String pattern
) {
208 final AnAction anAction
= myActionManager
.getAction(name
);
209 if (!(anAction
instanceof ActionGroup
)) {
210 final Presentation presentation
= anAction
.getTemplatePresentation();
211 final String text
= presentation
.getText();
212 final String description
= presentation
.getDescription();
213 final Pattern compiledPattern
= getPattern(pattern
);
214 if ((text
!= null && myMatcher
.matches(text
, compiledPattern
)) ||
215 (description
!= null && myMatcher
.matches(description
, compiledPattern
))) {
223 private Pattern
getPattern(String pattern
) {
224 if (!Comparing
.strEqual(pattern
, myPattern
)) {
225 myCompiledPattern
= null;
228 if (myCompiledPattern
== null) {
229 boolean allowToLower
= true;
230 final int eol
= pattern
.indexOf('\n');
232 pattern
= pattern
.substring(0, eol
);
234 if (pattern
.length() >= 80) {
235 pattern
= pattern
.substring(0, 80);
238 final @NonNls StringBuffer buffer
= new StringBuffer();
240 if (containsOnlyUppercaseLetters(pattern
)) {
241 allowToLower
= false;
248 boolean firstIdentifierLetter
= true;
249 for (int i
= 0; i
< pattern
.length(); i
++) {
250 final char c
= pattern
.charAt(i
);
251 if (Character
.isLetterOrDigit(c
)) {
252 // This logic allows to use uppercase letters only to catch the name like PDM for PsiDocumentManager
253 if (Character
.isUpperCase(c
) || Character
.isDigit(c
)) {
255 if (!firstIdentifierLetter
) {
256 buffer
.append("[^A-Z]*");
261 if (allowToLower
|| i
== 0) {
263 buffer
.append(Character
.toLowerCase(c
));
267 else if (Character
.isLowerCase(c
)) {
271 buffer
.append(Character
.toUpperCase(c
));
278 firstIdentifierLetter
= false;
282 firstIdentifierLetter
= true;
285 buffer
.append("\\.");
286 firstIdentifierLetter
= true;
289 buffer
.append("[^A-Z]*\\ ");
290 firstIdentifierLetter
= true;
293 firstIdentifierLetter
= true;
294 // for standard RegExp engine
295 // buffer.append("\\u");
296 // buffer.append(Integer.toHexString(c + 0x20000).substring(1));
298 // for OROMATCHER RegExp engine
299 buffer
.append("\\x");
300 buffer
.append(Integer
.toHexString(c
+ 0x20000).substring(3));
308 myCompiledPattern
= new Perl5Compiler().compile(buffer
.toString());
310 catch (MalformedPatternException e
) {
315 return myCompiledPattern
;
318 private static boolean containsOnlyUppercaseLetters(String s
) {
319 for (int i
= 0; i
< s
.length(); i
++) {
320 char c
= s
.charAt(i
);
321 if (c
!= '*' && c
!= ' ' && !Character
.isUpperCase(c
)) return false;