2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com
.intellij
.openapi
.actionSystem
.impl
;
18 import com
.intellij
.ide
.DataManager
;
19 import com
.intellij
.openapi
.actionSystem
.ActionGroup
;
20 import com
.intellij
.openapi
.actionSystem
.ActionPlaces
;
21 import com
.intellij
.openapi
.actionSystem
.DataContext
;
22 import com
.intellij
.openapi
.actionSystem
.Presentation
;
23 import com
.intellij
.openapi
.util
.IconLoader
;
24 import com
.intellij
.openapi
.util
.SystemInfo
;
25 import com
.intellij
.openapi
.wm
.StatusBar
;
26 import com
.intellij
.openapi
.wm
.impl
.IdeFrameImpl
;
27 import com
.intellij
.ui
.plaf
.beg
.IdeaMenuUI
;
28 import com
.intellij
.util
.ui
.UIUtil
;
31 import javax
.swing
.event
.MenuEvent
;
32 import javax
.swing
.event
.MenuListener
;
33 import javax
.swing
.plaf
.MenuItemUI
;
35 import java
.awt
.event
.KeyEvent
;
36 import java
.beans
.PropertyChangeEvent
;
37 import java
.beans
.PropertyChangeListener
;
39 public final class ActionMenu
extends JMenu
{
40 private final String myPlace
;
41 private DataContext myContext
;
42 private final ActionGroup myGroup
;
43 private final PresentationFactory myPresentationFactory
;
44 private final Presentation myPresentation
;
46 * Defines whether menu shows its mnemonic or not.
48 private boolean myMnemonicEnabled
;
49 private MenuItemSynchronizer myMenuItemSynchronizer
;
52 * Do not remove this STUPID code. Otherwise you will lose all keyboard navigation
55 private StubItem myStubItem
;
57 public ActionMenu(DataContext context
, String place
, ActionGroup group
, PresentationFactory presentationFactory
, final boolean enableMnemonics
) {
61 myPresentationFactory
= presentationFactory
;
62 myPresentation
= myPresentationFactory
.getPresentation(group
);
63 myMnemonicEnabled
= enableMnemonics
;
67 // addNotify won't be called for menus in MacOS system menu
68 if (SystemInfo
.isMacSystemMenu
) {
69 installSynchronizer();
73 public void updateContext(DataContext context
) {
77 public void addNotify() {
79 installSynchronizer();
82 private void installSynchronizer() {
83 if (myMenuItemSynchronizer
== null) {
84 myMenuItemSynchronizer
= new MenuItemSynchronizer();
85 myGroup
.addPropertyChangeListener(myMenuItemSynchronizer
);
86 myPresentation
.addPropertyChangeListener(myMenuItemSynchronizer
);
90 public void removeNotify() {
91 if (myMenuItemSynchronizer
!= null) {
92 myGroup
.removePropertyChangeListener(myMenuItemSynchronizer
);
93 myPresentation
.removePropertyChangeListener(myMenuItemSynchronizer
);
94 myMenuItemSynchronizer
= null;
99 public void updateUI() {
100 JPopupMenu popupMenu
= getPopupMenu();
101 if (popupMenu
!= null) {
102 popupMenu
.updateUI();
104 if (UIUtil
.isStandardMenuLAF()) {
105 setUI((MenuItemUI
)UIManager
.getUI(this));
108 setUI(IdeaMenuUI
.createUI(this));
109 setFont(UIUtil
.getMenuFont());
113 private void init() {
114 boolean macSystemMenu
= SystemInfo
.isMacSystemMenu
&& myPlace
== ActionPlaces
.MAIN_MENU
;
116 myStubItem
= macSystemMenu ?
null : new StubItem();
118 addMenuListener(new MenuListenerImpl());
119 setBorderPainted(false);
121 setVisible(myPresentation
.isVisible());
122 setEnabled(myPresentation
.isEnabled());
123 setText(myPresentation
.getText());
126 setMnemonicEnabled(myMnemonicEnabled
);
129 private void addStubItem() {
130 if (myStubItem
!= null) {
135 public void setMnemonicEnabled(boolean enable
) {
136 myMnemonicEnabled
= enable
;
137 setMnemonic(myPresentation
.getMnemonic());
138 setDisplayedMnemonicIndex(myPresentation
.getDisplayedMnemonicIndex());
142 public void setDisplayedMnemonicIndex(final int index
) throws IllegalArgumentException
{
143 super.setDisplayedMnemonicIndex(myMnemonicEnabled ? index
: -1);
146 public void setMnemonic(int mnemonic
) {
147 super.setMnemonic(myMnemonicEnabled ? mnemonic
: 0);
150 private void updateIcon() {
151 Presentation presentation
= myPresentation
;
152 Icon icon
= presentation
.getIcon();
154 if (presentation
.getDisabledIcon() != null) {
155 setDisabledIcon(presentation
.getDisabledIcon());
158 setDisabledIcon(IconLoader
.getDisabledIcon(icon
));
162 public void menuSelectionChanged(boolean isIncluded
) {
163 super.menuSelectionChanged(isIncluded
);
164 showDescriptionInStatusBar(isIncluded
, this, myPresentation
.getDescription());
167 public static void showDescriptionInStatusBar(boolean isIncluded
, Component component
, String description
) {
168 IdeFrameImpl frame
= component
instanceof IdeFrameImpl ?
(IdeFrameImpl
)component
:
169 (IdeFrameImpl
)SwingUtilities
.getAncestorOfClass(IdeFrameImpl
.class, component
);
171 StatusBar statusBar
= frame
.getStatusBar();
173 statusBar
.setInfo(description
);
176 statusBar
.setInfo(null);
182 private class MenuListenerImpl
implements MenuListener
{
183 public void menuCanceled(MenuEvent e
) {
188 public void menuDeselected(MenuEvent e
) {
194 public void menuSelected(MenuEvent e
) {
199 private void clearItems() {
200 if (SystemInfo
.isMacSystemMenu
&& myPlace
== ActionPlaces
.MAIN_MENU
) {
201 for (Component menuComponent
: getMenuComponents()) {
202 if (menuComponent
instanceof ActionMenu
) {
203 ((ActionMenu
)menuComponent
).clearItems();
205 else if (menuComponent
instanceof ActionMenuItem
) {
206 ((ActionMenuItem
)menuComponent
).setAccelerator(KeyStroke
.getKeyStroke(KeyEvent
.VK_F24
, 0));
215 private void fillMenu() {
216 DataContext context
= myContext
!= null ? myContext
: DataManager
.getInstance().getDataContext();
217 Utils
.fillMenu(myGroup
, this, myMnemonicEnabled
, myPresentationFactory
, context
, myPlace
, true);
220 private class MenuItemSynchronizer
implements PropertyChangeListener
{
221 public void propertyChange(PropertyChangeEvent e
) {
222 String name
= e
.getPropertyName();
223 if (Presentation
.PROP_VISIBLE
.equals(name
)) {
224 setVisible(myPresentation
.isVisible());
225 if (SystemInfo
.isMacSystemMenu
&& myPlace
== ActionPlaces
.MAIN_MENU
) {
229 else if (Presentation
.PROP_ENABLED
.equals(name
)) {
230 setEnabled(myPresentation
.isEnabled());
232 else if (Presentation
.PROP_MNEMONIC_KEY
.equals(name
)) {
233 setMnemonic(myPresentation
.getMnemonic());
235 else if (Presentation
.PROP_MNEMONIC_INDEX
.equals(name
)) {
236 setDisplayedMnemonicIndex(myPresentation
.getDisplayedMnemonicIndex());
238 else if (Presentation
.PROP_TEXT
.equals(name
)) {
239 setText(myPresentation
.getText());
241 else if (Presentation
.PROP_ICON
.equals(name
) || Presentation
.PROP_DISABLED_ICON
.equals(name
)) {