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
;
24 import java
.awt
.event
.ActionEvent
;
25 import java
.awt
.event
.ActionListener
;
26 import java
.awt
.image
.BufferedImage
;
31 public class ContextMenuImpl
extends JPanel
implements Disposable
{
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));
49 final ActionManager actionManager
= ActionManager
.getInstance();
51 editor
.addEditorMouseListener(new EditorMouseAdapter() {
53 public void mouseExited(final EditorMouseEvent e
) {
54 if (!isInsideActivationArea(container
, e
.getMouseEvent().getPoint())) {
55 toggleContextToolbar(false);
60 editor
.addEditorMouseMotionListener(new EditorMouseMotionAdapter() {
62 public void mouseMoved(final EditorMouseEvent e
) {
63 toggleContextToolbar(isInsideActivationArea(container
, e
.getMouseEvent().getPoint()));
67 AnAction action
= actionManager
.getAction("EditorContextBarMenu");
69 action
= new DefaultActionGroup();
70 actionManager
.registerAction(ACTION_GROUP
, action
);
73 if (action
instanceof ActionGroup
) {
74 myActionGroup
= (ActionGroup
)action
;
77 myComponent
= createComponent();
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
) {
102 public void dispose() {
106 if (myHideTimer
!= null) {
111 if (myShowTimer
!= null) {
118 public static boolean mayShowToolbar(@Nullable final Document document
) {
119 if (document
== null) {
123 final VirtualFile file
= FileDocumentManager
.getInstance().getFile(document
);
124 return file
!= null && file
.isValid() && file
.getFileSystem() == LocalFileSystem
.getInstance();
127 @SuppressWarnings({"deprecation"})
130 final Component toolbar
= myComponent
.getComponent(0);
131 final int count
= ((Container
)toolbar
).getComponentCount();
137 //myCurrentOpacity = 0;
139 if (myHideTimer
!= null && myHideTimer
.isRunning()) {
147 if (myShowTimer
== null || !myShowTimer
.isRunning()) {
150 myShowTimer
= new Timer(500, new ActionListener() {
151 public void actionPerformed(final ActionEvent e
) {
152 if (myDisposed
|| myShowTimer
== null) return;
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;
171 myShowTimer
.setRepeats(true);
176 myShowTimer
.setRepeats(false);
187 private void scheduleHide() {
188 if (myHideTimer
!= null && myHideTimer
.isRunning()) {
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);
213 @SuppressWarnings({"deprecation"})
217 if (myShowTimer
!= null && myShowTimer
.isRunning()) {
222 if (myHideTimer
== null || !myHideTimer
.isRunning()) {
225 myHideTimer
= new Timer(700, new ActionListener() {
226 public void actionPerformed(final ActionEvent e
) {
227 if (myDisposed
|| myHideTimer
== null) return;
230 myHideTimer
= new Timer(50, new ActionListener() {
231 public void actionPerformed(final ActionEvent e
) {
232 myCurrentOpacity
-= 20;
233 if (myCurrentOpacity
< 0) {
234 myCurrentOpacity
= 0;
236 //ContextMenuImpl.super.hide();
243 myHideTimer
.setRepeats(true);
248 myHideTimer
.setRepeats(false);
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()) {
263 public void paint(final Graphics g
) {
264 if (myContextMenuPanel
.isPaintChildren()) {
270 protected void paintChildren(final Graphics g
) {
271 if (myContextMenuPanel
.isPaintChildren()) {
272 super.paintChildren(g
);
277 public boolean isOpaque() {
278 return myContextMenuPanel
.isPaintChildren();
282 public ActionButton
createToolbarButton(final AnAction action
,
283 final ActionButtonLook look
,
285 final Presentation presentation
,
286 final Dimension minimumSize
) {
287 final ActionButton result
= new ActionButton(action
, presentation
, place
, minimumSize
) {
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());
303 public boolean isOpaque() {
304 return myContextMenuPanel
.isPaintChildren() || getPopState() == ActionButton
.POPPED
;
308 public void paint(final Graphics g
) {
309 final Graphics2D g2
= (Graphics2D
)g
;
314 result
.setLook(look
);
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));
348 public void invalidate() {
351 myBufferedImage
= null;
355 public void revalidate() {
358 myBufferedImage
= null;
362 protected void paintChildren(final Graphics g
) {
363 if (myPaintChildren
) {
364 super.paintChildren(g
);
368 public boolean isPaintChildren() {
369 return myPaintChildren
;
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;
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;