optimization: replace all occurrence is dramatically faster
[fedora-idea.git] / platform-impl / src / com / intellij / openapi / editor / impl / ContextMenuImpl.java
blobc11aa0c095aa72e20db75bd9657104090dcbf6ed
1 package com.intellij.openapi.editor.impl;
3 import com.intellij.ide.DataManager;
4 import com.intellij.openapi.Disposable;
5 import com.intellij.openapi.fileEditor.FileDocumentManager;
6 import com.intellij.openapi.actionSystem.*;
7 import com.intellij.openapi.actionSystem.ex.ActionButtonLook;
8 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
9 import com.intellij.openapi.actionSystem.impl.ActionButton;
10 import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
11 import com.intellij.openapi.editor.Document;
12 import com.intellij.openapi.editor.event.EditorMouseAdapter;
13 import com.intellij.openapi.editor.event.EditorMouseEvent;
14 import com.intellij.openapi.editor.event.EditorMouseMotionAdapter;
15 import com.intellij.openapi.keymap.ex.KeymapManagerEx;
16 import com.intellij.openapi.vfs.LocalFileSystem;
17 import com.intellij.openapi.vfs.VirtualFile;
18 import org.jetbrains.annotations.NonNls;
19 import org.jetbrains.annotations.NotNull;
20 import org.jetbrains.annotations.Nullable;
22 import javax.swing.*;
23 import java.awt.*;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.awt.image.BufferedImage;
28 /**
29 * @author spleaner
31 public class ContextMenuImpl extends JPanel implements Disposable {
32 @NonNls
33 public static final String ACTION_GROUP = "EditorContextBarMenu";
35 private ActionGroup myActionGroup;
36 private final JComponent myComponent;
37 private boolean myShowing = false;
38 private int myCurrentOpacity;
39 private Timer myShowTimer;
40 private Timer myHideTimer;
41 private EditorImpl myEditor;
42 private ContextMenuPanel myContextMenuPanel;
43 private boolean myDisposed;
45 public ContextMenuImpl(@NotNull final JScrollPane container, @NotNull final EditorImpl editor) {
46 setLayout(new BorderLayout(0, 0));
47 myEditor = editor;
49 final ActionManager actionManager = ActionManager.getInstance();
51 editor.addEditorMouseListener(new EditorMouseAdapter() {
52 @Override
53 public void mouseExited(final EditorMouseEvent e) {
54 if (!isInsideActivationArea(container, e.getMouseEvent().getPoint())) {
55 toggleContextToolbar(false);
58 });
60 editor.addEditorMouseMotionListener(new EditorMouseMotionAdapter() {
61 @Override
62 public void mouseMoved(final EditorMouseEvent e) {
63 toggleContextToolbar(isInsideActivationArea(container, e.getMouseEvent().getPoint()));
65 });
67 AnAction action = actionManager.getAction("EditorContextBarMenu");
68 if (action == null) {
69 action = new DefaultActionGroup();
70 actionManager.registerAction(ACTION_GROUP, action);
73 if (action instanceof ActionGroup) {
74 myActionGroup = (ActionGroup)action;
77 myComponent = createComponent();
78 add(myComponent);
80 setVisible(false);
81 setOpaque(false);
84 private static boolean isInsideActivationArea(JScrollPane container, Point p) {
85 final JViewport viewport = container.getViewport();
86 final Rectangle r = viewport.getBounds();
87 final Point viewPosition = viewport.getViewPosition();
89 final Rectangle activationArea = new Rectangle(0, 0, r.width, 150);
90 return activationArea.contains(p.x, p.y - viewPosition.y);
93 private void toggleContextToolbar(final boolean show) {
94 if (show) {
95 show();
97 else {
98 hide();
102 public void dispose() {
103 myDisposed = true;
104 myEditor = null;
106 if (myHideTimer != null) {
107 myHideTimer.stop();
108 myHideTimer = null;
111 if (myShowTimer != null) {
112 myShowTimer.stop();
113 myShowTimer = null;
118 public static boolean mayShowToolbar(@Nullable final Document document) {
119 if (document == null) {
120 return false;
123 final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
124 return file != null && file.isValid() && file.getFileSystem() == LocalFileSystem.getInstance();
127 @SuppressWarnings({"deprecation"})
128 @Override
129 public void show() {
130 final Component toolbar = myComponent.getComponent(0);
131 final int count = ((Container)toolbar).getComponentCount();
132 if (count == 0) {
133 return;
136 if (!myShowing) {
137 //myCurrentOpacity = 0;
139 if (myHideTimer != null && myHideTimer.isRunning()) {
140 myHideTimer.stop();
141 myHideTimer = null;
144 super.show();
145 setOpaque(false);
147 if (myShowTimer == null || !myShowTimer.isRunning()) {
148 myShowing = true;
150 myShowTimer = new Timer(500, new ActionListener() {
151 public void actionPerformed(final ActionEvent e) {
152 if (myDisposed || myShowTimer == null) return;
153 myShowTimer.stop();
155 myShowTimer = new Timer(50, new ActionListener() {
156 public void actionPerformed(final ActionEvent e) {
157 if (myDisposed) return;
159 myCurrentOpacity += 20;
160 if (myCurrentOpacity > 100) {
161 myCurrentOpacity = 100;
162 myShowTimer.stop();
164 scheduleHide();
167 repaint();
171 myShowTimer.setRepeats(true);
172 myShowTimer.start();
176 myShowTimer.setRepeats(false);
177 myShowTimer.start();
181 else {
182 scheduleHide();
183 super.show();
187 private void scheduleHide() {
188 if (myHideTimer != null && myHideTimer.isRunning()) {
189 return;
192 myHideTimer = new Timer(1500, new ActionListener() {
193 public void actionPerformed(final ActionEvent e) {
194 if (myDisposed) return;
196 if (myComponent.isVisible()) {
197 final PointerInfo pointerInfo = MouseInfo.getPointerInfo();
198 if (pointerInfo != null) {
199 final Point location = pointerInfo.getLocation();
200 SwingUtilities.convertPointFromScreen(location, myComponent);
201 if (!myComponent.getBounds().contains(location)) {
202 toggleContextToolbar(false);
209 myHideTimer.setRepeats(false);
210 myHideTimer.start();
213 @SuppressWarnings({"deprecation"})
214 @Override
215 public void hide() {
216 if (myShowing) {
217 if (myShowTimer != null && myShowTimer.isRunning()) {
218 myShowTimer.stop();
219 myShowTimer = null;
222 if (myHideTimer == null || !myHideTimer.isRunning()) {
223 myShowing = false;
225 myHideTimer = new Timer(700, new ActionListener() {
226 public void actionPerformed(final ActionEvent e) {
227 if (myDisposed || myHideTimer == null) return;
228 myHideTimer.stop();
230 myHideTimer = new Timer(50, new ActionListener() {
231 public void actionPerformed(final ActionEvent e) {
232 myCurrentOpacity -= 20;
233 if (myCurrentOpacity < 0) {
234 myCurrentOpacity = 0;
235 myHideTimer.stop();
236 //ContextMenuImpl.super.hide();
239 repaint();
243 myHideTimer.setRepeats(true);
244 myHideTimer.start();
248 myHideTimer.setRepeats(false);
249 myHideTimer.start();
252 else {
253 //super.hide();
257 private ActionToolbar createToolbar(final ActionGroup group) {
258 final ActionToolbarImpl actionToolbar =
259 new ActionToolbarImpl(ActionPlaces.CONTEXT_TOOLBAR, group, true, DataManager.getInstance(), ActionManagerEx.getInstanceEx(),
260 KeymapManagerEx.getInstanceEx()) {
262 @Override
263 public void paint(final Graphics g) {
264 if (myContextMenuPanel.isPaintChildren()) {
265 paintChildren(g);
269 @Override
270 protected void paintChildren(final Graphics g) {
271 if (myContextMenuPanel.isPaintChildren()) {
272 super.paintChildren(g);
276 @Override
277 public boolean isOpaque() {
278 return myContextMenuPanel.isPaintChildren();
281 @Override
282 public ActionButton createToolbarButton(final AnAction action,
283 final ActionButtonLook look,
284 final String place,
285 final Presentation presentation,
286 final Dimension minimumSize) {
287 final ActionButton result = new ActionButton(action, presentation, place, minimumSize) {
288 @Override
289 public void paintComponent(final Graphics g) {
290 if (myContextMenuPanel.isPaintChildren()) {
291 final ActionButtonLook look = getButtonLook();
292 look.paintIcon(g, this, getIcon());
295 if (myContextMenuPanel.isShown() && getPopState() == ActionButton.POPPED) {
296 final ActionButtonLook look = getButtonLook();
297 look.paintBackground(g, this);
298 look.paintIcon(g, this, getIcon());
302 @Override
303 public boolean isOpaque() {
304 return myContextMenuPanel.isPaintChildren() || getPopState() == ActionButton.POPPED;
307 @Override
308 public void paint(final Graphics g) {
309 final Graphics2D g2 = (Graphics2D)g;
310 paintComponent(g2);
314 result.setLook(look);
315 return result;
319 actionToolbar.setTargetComponent(myEditor.getContentComponent());
321 return actionToolbar;
324 private JComponent createComponent() {
325 final ActionToolbar toolbar = createToolbar(myActionGroup);
326 toolbar.setMinimumButtonSize(new Dimension(20, 20));
327 toolbar.setReservePlaceAutoPopupIcon(false);
329 myContextMenuPanel = new ContextMenuPanel(this);
330 myContextMenuPanel.setLayout(new BorderLayout(0, 0));
331 myContextMenuPanel.add(toolbar.getComponent());
333 return myContextMenuPanel;
336 private static class ContextMenuPanel extends JPanel {
337 private final ContextMenuImpl myContextMenu;
338 private BufferedImage myBufferedImage;
339 private boolean myPaintChildren = false;
341 private ContextMenuPanel(final ContextMenuImpl contextMenu) {
342 myContextMenu = contextMenu;
343 setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
344 setOpaque(false);
347 @Override
348 public void invalidate() {
349 super.invalidate();
351 myBufferedImage = null;
354 @Override
355 public void revalidate() {
356 super.revalidate();
358 myBufferedImage = null;
361 @Override
362 protected void paintChildren(final Graphics g) {
363 if (myPaintChildren) {
364 super.paintChildren(g);
368 public boolean isPaintChildren() {
369 return myPaintChildren;
372 @Override
373 public void paint(final Graphics g) {
374 final Rectangle r = getBounds();
375 if (myBufferedImage == null) {
376 myBufferedImage = new BufferedImage(r.width, r.height, BufferedImage.TYPE_INT_ARGB);
378 final Graphics graphics = myBufferedImage.getGraphics();
379 final Graphics2D g2d2 = (Graphics2D)graphics;
380 final Composite old = g2d2.getComposite();
382 g2d2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
384 g2d2.setColor(Color.GRAY);
385 g2d2.fillRoundRect(0, 0, r.width - 1, r.height - 1, 6, 6);
387 g2d2.setComposite(old);
389 myPaintChildren = true;
390 paintChildren(g2d2);
391 myPaintChildren = false;
394 final Graphics2D g2 = (Graphics2D)g;
395 final Composite old = g2.getComposite();
397 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, myContextMenu.myCurrentOpacity / 100.0f));
398 g2.drawImage(myBufferedImage, 0, 0, myBufferedImage.getWidth(null), myBufferedImage.getHeight(null), null);
400 g2.setComposite(old);
403 public boolean isShown() {
404 return myContextMenu.myCurrentOpacity == 100;