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
.ui
.impl
;
18 import com
.intellij
.ide
.DataManager
;
19 import com
.intellij
.ide
.IdeEventQueue
;
20 import com
.intellij
.ide
.impl
.TypeSafeDataProviderAdapter
;
21 import com
.intellij
.ide
.ui
.UISettings
;
22 import com
.intellij
.openapi
.Disposable
;
23 import com
.intellij
.openapi
.actionSystem
.*;
24 import com
.intellij
.openapi
.application
.Application
;
25 import com
.intellij
.openapi
.application
.ApplicationManager
;
26 import com
.intellij
.openapi
.application
.impl
.LaterInvocator
;
27 import com
.intellij
.openapi
.command
.CommandProcessor
;
28 import com
.intellij
.openapi
.command
.CommandProcessorEx
;
29 import com
.intellij
.openapi
.diagnostic
.Logger
;
30 import com
.intellij
.openapi
.project
.DumbAware
;
31 import com
.intellij
.openapi
.project
.Project
;
32 import com
.intellij
.openapi
.ui
.DialogWrapper
;
33 import com
.intellij
.openapi
.ui
.DialogWrapperDialog
;
34 import com
.intellij
.openapi
.ui
.DialogWrapperPeer
;
35 import com
.intellij
.openapi
.ui
.TestableUi
;
36 import com
.intellij
.openapi
.ui
.popup
.StackingPopupDispatcher
;
37 import com
.intellij
.openapi
.util
.*;
38 import com
.intellij
.openapi
.util
.registry
.Registry
;
39 import com
.intellij
.openapi
.wm
.FocusCommand
;
40 import com
.intellij
.openapi
.wm
.IdeFocusManager
;
41 import com
.intellij
.openapi
.wm
.KeyEventProcessor
;
42 import com
.intellij
.openapi
.wm
.WindowManager
;
43 import com
.intellij
.openapi
.wm
.ex
.WindowManagerEx
;
44 import com
.intellij
.openapi
.wm
.impl
.IdeFrameImpl
;
45 import com
.intellij
.openapi
.wm
.impl
.IdeGlassPaneImpl
;
46 import com
.intellij
.ui
.AppUIUtil
;
47 import com
.intellij
.ui
.FocusTrackback
;
48 import com
.intellij
.ui
.ScreenUtil
;
49 import com
.intellij
.ui
.SpeedSearchBase
;
50 import com
.intellij
.ui
.popup
.StackingPopupDispatcherImpl
;
51 import com
.intellij
.util
.ui
.UIUtil
;
52 import org
.jetbrains
.annotations
.NonNls
;
53 import org
.jetbrains
.annotations
.NotNull
;
54 import org
.jetbrains
.annotations
.Nullable
;
58 import java
.awt
.event
.*;
59 import java
.awt
.image
.BufferStrategy
;
60 import java
.lang
.ref
.WeakReference
;
61 import java
.lang
.reflect
.Field
;
62 import java
.lang
.reflect
.Method
;
63 import java
.util
.ArrayList
;
64 import java
.util
.List
;
67 public class DialogWrapperPeerImpl
extends DialogWrapperPeer
implements FocusTrackbackProvider
{
68 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.ui.DialogWrapper");
70 private DialogWrapper myWrapper
;
71 private MyDialog myDialog
;
72 private boolean myCanBeParent
= true;
74 * Default dialog's actions.
76 private WindowManagerEx myWindowManager
;
77 private final java
.util
.List
<Runnable
> myDisposeActions
= new ArrayList
<Runnable
>();
78 private Project myProject
;
80 private ActionCallback myWindowFocusedCallback
= new ActionCallback("DialogFocusedCallback");
81 private ActionCallback myTypeAheadDone
= new ActionCallback("DialogTypeAheadDone");
84 * Creates modal <code>DialogWrapper</code>. The currently active window will be the dialog's parent.
86 * @param project parent window for the dialog will be calculated based on focused window for the
87 * specified <code>project</code>. This parameter can be <code>null</code>. In this case parent window
88 * will be suggested based on current focused window.
89 * @param canBeParent specifies whether the dialog can be parent for other windows. This parameter is used
90 * by <code>WindowManager</code>.
92 protected DialogWrapperPeerImpl(DialogWrapper wrapper
, Project project
, boolean canBeParent
) {
94 myWindowManager
= null;
95 Application application
= ApplicationManager
.getApplication();
96 if (application
!= null && application
.hasComponent(WindowManager
.class)) {
97 myWindowManager
= (WindowManagerEx
)WindowManager
.getInstance();
100 Window window
= null;
101 if (myWindowManager
!= null) {
103 if (project
== null) {
104 project
= PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext());
109 window
= myWindowManager
.suggestParentWindow(project
);
110 if (window
== null) {
111 Window focusedWindow
= myWindowManager
.getMostRecentFocusedWindow();
112 if (focusedWindow
instanceof IdeFrameImpl
) {
113 window
= focusedWindow
;
119 if (window
!= null) {
123 owner
= JOptionPane
.getRootFrame();
126 createDialog(owner
, canBeParent
);
129 protected DialogWrapperPeerImpl(DialogWrapper wrapper
, boolean canBeParent
) {
130 this(wrapper
, (Project
)null, canBeParent
);
134 * @param parent parent component whicg is used to canculate heavy weight window ancestor.
135 * <code>parent</code> cannot be <code>null</code> and must be showing.
137 protected DialogWrapperPeerImpl(DialogWrapper wrapper
, @NotNull Component parent
, boolean canBeParent
) {
139 if (!parent
.isShowing() && parent
!= JOptionPane
.getRootFrame()) {
140 throw new IllegalArgumentException("parent must be showing: " + parent
);
142 myWindowManager
= null;
143 Application application
= ApplicationManager
.getApplication();
144 if (application
!= null && application
.hasComponent(WindowManager
.class)) {
145 myWindowManager
= (WindowManagerEx
)WindowManager
.getInstance();
148 Window owner
= parent
instanceof Window ?
(Window
)parent
: (Window
)SwingUtilities
.getAncestorOfClass(Window
.class, parent
);
149 if (!(owner
instanceof Dialog
) && !(owner
instanceof Frame
)) {
150 owner
= JOptionPane
.getRootFrame();
152 createDialog(owner
, canBeParent
);
155 public DialogWrapperPeerImpl(final DialogWrapper wrapper
, final boolean canBeParent
, final boolean tryToolkitModal
) {
157 myWindowManager
= null;
158 Application application
= ApplicationManager
.getApplication();
159 if (application
!= null && application
.hasComponent(WindowManager
.class)) {
160 myWindowManager
= (WindowManagerEx
)WindowManager
.getInstance();
162 if (UIUtil
.hasJdk6Dialogs()) {
163 createDialog(null, canBeParent
);
164 if (tryToolkitModal
) {
165 UIUtil
.setToolkitModal(myDialog
);
169 createDialog(JOptionPane
.getRootFrame(), canBeParent
);
173 public void setUndecorated(boolean undecorated
) {
174 myDialog
.setUndecorated(undecorated
);
177 public void addMouseListener(MouseListener listener
) {
178 myDialog
.addMouseListener(listener
);
181 public void addMouseListener(MouseMotionListener listener
) {
182 myDialog
.addMouseMotionListener(listener
);
185 public void addKeyListener(KeyListener listener
) {
186 myDialog
.addKeyListener(listener
);
189 private void createDialog(Window owner
, boolean canBeParent
) {
190 if (owner
instanceof Frame
) {
191 myDialog
= new MyDialog((Frame
)owner
, myWrapper
, myProject
, myWindowFocusedCallback
, myTypeAheadDone
);
194 myDialog
= new MyDialog((Dialog
)owner
, myWrapper
, myProject
, myWindowFocusedCallback
, myTypeAheadDone
);
196 myDialog
.setModal(true);
197 myCanBeParent
= canBeParent
;
202 public void toFront() {
206 public void toBack() {
210 protected void dispose() {
211 LOG
.assertTrue(EventQueue
.isDispatchThread(), "Access is allowed from event dispatch thread only");
212 for (Runnable runnable
: myDisposeActions
) {
215 myDisposeActions
.clear();
216 final JRootPane root
= myDialog
.getRootPane();
218 Runnable disposer
= new Runnable() {
223 if (myWindowManager == null) {
227 myWindowManager.hideDialog(myDialog, myProject);
231 SwingUtilities
.invokeLater(new Runnable() {
233 if (myDialog
!= null && root
!= null) {
234 myDialog
.remove(root
);
241 if (EventQueue
.isDispatchThread()) {
245 SwingUtilities
.invokeLater(disposer
);
249 private boolean isProgressDialog() {
250 return myWrapper
.isModalProgress();
254 public Container
getContentPane() {
255 return getRootPane() != null ? myDialog
.getContentPane() : null;
259 * @see javax.swing.JDialog#validate
261 public void validate() {
266 * @see javax.swing.JDialog#repaint
268 public void repaint() {
272 public Window
getOwner() {
273 return myDialog
.getOwner();
276 public Window
getWindow() {
280 public JRootPane
getRootPane() {
281 return myDialog
.getRootPane();
284 public Dimension
getSize() {
285 return myDialog
.getSize();
288 public String
getTitle() {
289 return myDialog
.getTitle();
293 * @see java.awt.Window#pack
299 public void setIconImages(final List
<Image
> image
) {
300 UIUtil
.updateDialogIcon(myDialog
, image
);
303 public void setAppIcons() {
304 setIconImages(AppUIUtil
.getAppIconImages());
307 public Dimension
getPreferredSize() {
308 return myDialog
.getPreferredSize();
311 public void setModal(boolean modal
) {
312 myDialog
.setModal(modal
);
315 public boolean isVisible() {
316 return myDialog
.isVisible();
319 public boolean isShowing() {
320 return myDialog
.isShowing();
323 public void setSize(int width
, int height
) {
324 myDialog
.setSize(width
, height
);
327 public void setTitle(String title
) {
328 myDialog
.setTitle(title
);
331 public void isResizable() {
332 myDialog
.isResizable();
335 public void setResizable(boolean resizable
) {
336 myDialog
.setResizable(resizable
);
339 public Point
getLocation() {
340 return myDialog
.getLocation();
343 public void setLocation(Point p
) {
344 myDialog
.setLocation(p
);
347 public void setLocation(int x
, int y
) {
348 myDialog
.setLocation(x
, y
);
351 public ActionCallback
show() {
352 final ActionCallback result
= new ActionCallback();
354 LOG
.assertTrue(EventQueue
.isDispatchThread(), "Access is allowed from event dispatch thread only");
356 final AnCancelAction anCancelAction
= new AnCancelAction();
357 final JRootPane rootPane
= getRootPane();
358 anCancelAction
.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke
.getKeyStroke(KeyEvent
.VK_ESCAPE
, 0)), rootPane
);
359 myDisposeActions
.add(new Runnable() {
361 anCancelAction
.unregisterCustomShortcutSet(rootPane
);
365 if (!myCanBeParent
&& myWindowManager
!= null) {
366 myWindowManager
.doNotSuggestAsParent(myDialog
);
369 final CommandProcessorEx commandProcessor
=
370 ApplicationManager
.getApplication() != null ?
(CommandProcessorEx
)CommandProcessor
.getInstance() : null;
371 final boolean appStarted
= commandProcessor
!= null;
373 if (myDialog
.isModal() && !isProgressDialog()) {
375 if (ApplicationManager.getApplication() != null) {
376 if (ApplicationManager.getApplication().getCurrentWriteAction(null) != null) {
378 "Showing of a modal dialog inside write-action may be dangerous and resulting in unpredictable behavior! Current modalityState=" + ModalityState.current(), new Exception());
383 commandProcessor
.enterModal();
384 LaterInvocator
.enterModal(myDialog
);
389 hidePopupsIfNeeded();
396 if (myDialog
.isModal() && !isProgressDialog()) {
398 commandProcessor
.leaveModal();
399 LaterInvocator
.leaveModal(myDialog
);
403 myDialog
.getFocusManager().doWhenFocusSettlesDown(new Runnable() {
413 //[kirillk] for now it only deals with the TaskWindow under Mac OS X: modal dialogs are shown behind JBPopup
415 //hopefully this whole code will go away
416 private void hidePopupsIfNeeded() {
417 if (!SystemInfo
.isMac
) return;
419 StackingPopupDispatcherImpl
.getInstance().hidePersistentPopups();
420 myDisposeActions
.add(new Runnable() {
422 StackingPopupDispatcherImpl
.getInstance().restorePersistentPopups();
427 public FocusTrackback
getFocusTrackback() {
428 return myDialog
.getFocusTrackback();
431 private class AnCancelAction
extends AnAction
implements DumbAware
{
432 public void update(AnActionEvent e
) {
433 Component focusOwner
= KeyboardFocusManager
.getCurrentKeyboardFocusManager().getFocusOwner();
434 e
.getPresentation().setEnabled(false);
435 if (focusOwner
instanceof JComponent
&& SpeedSearchBase
.hasActiveSpeedSearch((JComponent
)focusOwner
)) {
439 if (StackingPopupDispatcher
.getInstance().isPopupFocused()) return;
441 if (focusOwner
instanceof JTree
) {
442 JTree tree
= (JTree
)focusOwner
;
443 if (!tree
.isEditing()) {
444 e
.getPresentation().setEnabled(true);
447 else if (focusOwner
instanceof JTable
) {
448 JTable table
= (JTable
)focusOwner
;
449 if (!table
.isEditing()) {
450 e
.getPresentation().setEnabled(true);
455 public void actionPerformed(AnActionEvent e
) {
456 myWrapper
.doCancelAction(e
.getInputEvent());
461 private static class MyDialog
extends JDialog
implements DialogWrapperDialog
, DataProvider
, FocusTrackback
.Provider
, TestableUi
{
462 private final WeakReference
<DialogWrapper
> myDialogWrapper
;
464 * Initial size of the dialog. When the dialog is being closed and
465 * current size of the dialog is not equals to the initial sizethen the
466 * current (changed) size is stored in the <code>DimensionService</code>.
468 private Dimension myInitialSize
;
469 private String myDimensionServiceKey
;
470 private boolean myOpened
= false;
472 private FocusTrackback myFocusTrackback
;
473 private MyDialog
.MyWindowListener myWindowListener
;
474 private MyDialog
.MyComponentListener myComponentListener
;
476 private final WeakReference
<Project
> myProject
;
477 private ActionCallback myFocusedCallback
;
478 private ActionCallback myTypeAheadDone
;
480 public MyDialog(Dialog owner
, DialogWrapper dialogWrapper
, Project project
, ActionCallback focused
, ActionCallback typeAheadDone
) {
482 myDialogWrapper
= new WeakReference
<DialogWrapper
>(dialogWrapper
);
483 myProject
= project
!= null ?
new WeakReference
<Project
>(project
) : null;
484 initDialog(focused
, typeAheadDone
);
487 public MyDialog(Frame owner
, DialogWrapper dialogWrapper
, Project project
, ActionCallback focused
, ActionCallback typeAheadDone
) {
489 myDialogWrapper
= new WeakReference
<DialogWrapper
>(dialogWrapper
);
490 myProject
= project
!= null ?
new WeakReference
<Project
>(project
) : null;
491 initDialog(focused
, typeAheadDone
);
494 private void initDialog(ActionCallback focused
, ActionCallback typeAheadDone
) {
495 myFocusedCallback
= focused
;
496 myTypeAheadDone
= typeAheadDone
;
498 final long typeAhead
= getDialogWrapper().getTypeAheadTimeoutMs();
499 if (typeAhead
<= 0) {
500 myTypeAheadDone
.setDone();
503 setDefaultCloseOperation(WindowConstants
.DO_NOTHING_ON_CLOSE
);
504 myWindowListener
= new MyWindowListener();
505 addWindowListener(myWindowListener
);
506 myComponentListener
= new MyComponentListener();
507 addComponentListener(myComponentListener
);
510 public void putInfo(Map
<String
, String
> info
) {
511 info
.put("dialog", getTitle());
514 public FocusTrackback
getFocusTrackback() {
515 return myFocusTrackback
;
518 public DialogWrapper
getDialogWrapper() {
519 return myDialogWrapper
.get();
522 public void centerInParent() {
523 setLocationRelativeTo(getOwner());
526 public Object
getData(String dataId
) {
527 final DialogWrapper wrapper
= myDialogWrapper
.get();
528 if (wrapper
instanceof DataProvider
) {
529 return ((DataProvider
)wrapper
).getData(dataId
);
531 else if (wrapper
instanceof TypeSafeDataProvider
) {
532 TypeSafeDataProviderAdapter adapter
= new TypeSafeDataProviderAdapter((TypeSafeDataProvider
)wrapper
);
533 return adapter
.getData(dataId
);
538 public void setSize(int width
, int height
) {
539 Point location
= getLocation();
540 Rectangle rect
= new Rectangle(location
.x
, location
.y
, width
, height
);
541 ScreenUtil
.fitToScreen(rect
);
542 if (location
.x
!= rect
.x
|| location
.y
!= rect
.y
) {
543 setLocation(rect
.x
, rect
.y
);
546 super.setSize(rect
.width
, rect
.height
);
549 public void setBounds(int x
, int y
, int width
, int height
) {
550 Rectangle rect
= new Rectangle(x
, y
, width
, height
);
551 ScreenUtil
.fitToScreen(rect
);
552 super.setBounds(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
555 public void setBounds(Rectangle r
) {
556 ScreenUtil
.fitToScreen(r
);
560 protected JRootPane
createRootPane() {
561 return new DialogRootPane();
565 myFocusTrackback
= new FocusTrackback(myDialogWrapper
, this, true);
567 final DialogWrapper dialogWrapper
= getDialogWrapper();
570 setSize((int)(getWidth() * dialogWrapper
.getHorizontalStretch()), (int)(getHeight() * dialogWrapper
.getVerticalStretch()));
572 // Restore dialog's size and location
574 myDimensionServiceKey
= dialogWrapper
.getDimensionKey();
575 Point location
= null;
577 if (myDimensionServiceKey
!= null) {
578 final Project projectGuess
= PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext(this));
579 location
= DimensionService
.getInstance().getLocation(myDimensionServiceKey
, projectGuess
);
580 Dimension size
= DimensionService
.getInstance().getSize(myDimensionServiceKey
, projectGuess
);
582 myInitialSize
= (Dimension
)size
.clone();
583 setSize(myInitialSize
);
587 if (myInitialSize
== null) {
588 myInitialSize
= getSize();
591 if (location
== null) {
592 location
= dialogWrapper
.getInitialLocation();
595 if (location
!= null) {
596 setLocation(location
);
599 setLocationRelativeTo(getOwner());
602 final Rectangle bounds
= getBounds();
603 ScreenUtil
.fitToScreen(bounds
);
606 addWindowListener(new WindowAdapter() {
607 public void windowActivated(final WindowEvent e
) {
608 final DialogWrapper wrapper
= getDialogWrapper();
609 if (wrapper
!= null && myFocusTrackback
!= null) {
610 myFocusTrackback
.registerFocusComponent(new FocusTrackback
.ComponentQuery() {
611 public Component
getComponent() {
612 return wrapper
.getPreferredFocusedComponent();
618 public void windowDeactivated(final WindowEvent e
) {
620 final Ref
<IdeFocusManager
> focusManager
= new Ref
<IdeFocusManager
>(null);
621 if (myProject
!= null && myProject
.get() != null && !myProject
.get().isDisposed()) {
622 focusManager
.set(getFocusManager());
623 focusManager
.get().doWhenFocusSettlesDown(new Runnable() {
625 disposeFocusTrackbackIfNoChildWindowFocused(focusManager
.get());
630 disposeFocusTrackbackIfNoChildWindowFocused(focusManager
.get());
636 if (Registry
.is("actionSystem.fixLostTyping")) {
637 final IdeEventQueue queue
= IdeEventQueue
.getInstance();
639 queue
.getKeyEventDispatcher().resetState();
642 if (myProject
!= null) {
643 Project project
= myProject
.get();
644 if (project
!= null && !project
.isDisposed() && project
.isInitialized()) {
645 IdeFocusManager
.findInstanceByComponent(this).requestFocus(new MyFocusCommand(dialogWrapper
), true);
653 private IdeFocusManager
getFocusManager() {
654 if (myProject
!= null && myProject
.get() != null && !myProject
.get().isDisposed()) {
655 return IdeFocusManager
.getInstance(myProject
.get());
657 return IdeFocusManager
.findInstance();
661 private void disposeFocusTrackbackIfNoChildWindowFocused(@Nullable IdeFocusManager focusManager
) {
662 if (myFocusTrackback
== null) return;
664 final DialogWrapper wrapper
= myDialogWrapper
.get();
665 if (wrapper
== null || !wrapper
.isShowing()) {
666 myFocusTrackback
.dispose();
670 if (focusManager
!= null) {
671 final Component c
= focusManager
.getFocusedDescendantFor(wrapper
.getContentPane());
673 myFocusTrackback
.dispose();
677 final Component owner
= KeyboardFocusManager
.getCurrentKeyboardFocusManager().getFocusOwner();
678 if (owner
== null || !SwingUtilities
.isDescendingFrom(owner
, wrapper
.getContentPane())) {
679 myFocusTrackback
.dispose();
687 if (myFocusTrackback
!= null && !(myFocusTrackback
.isSheduledForRestore() || myFocusTrackback
.isWillBeSheduledForRestore())) {
688 myFocusTrackback
.setWillBeSheduledForRestore();
689 IdeFocusManager mgr
= getFocusManager();
690 Runnable r
= new Runnable() {
692 myFocusTrackback
.restoreFocus();
693 myFocusTrackback
= null;
696 mgr
.doWhenFocusSettlesDown(r
);
700 public void dispose() {
705 if (myWindowListener
!= null) {
706 myWindowListener
.saveSize();
707 removeWindowListener(myWindowListener
);
708 myWindowListener
= null;
710 if (myComponentListener
!= null) {
711 removeComponentListener(myComponentListener
);
712 myComponentListener
= null;
715 if (myFocusTrackback
!= null && !(myFocusTrackback
.isSheduledForRestore() || myFocusTrackback
.isWillBeSheduledForRestore())) {
716 myFocusTrackback
.dispose();
717 myFocusTrackback
= null;
721 final BufferStrategy strategy
= getBufferStrategy();
722 if (strategy
!= null) {
724 Method method
= strategy
.getClass().getMethod("dispose"); // added in JDK 1.6 so cannot call directly
725 method
.invoke(strategy
);
727 catch (Exception ex
) {
734 if (rootPane
!= null) { // Workaround for bug in native code to hold rootPane
736 Field field
= rootPane
.getClass().getDeclaredField("glassPane");
737 field
.setAccessible(true);
738 field
.set(rootPane
, null);
740 field
= rootPane
.getClass().getDeclaredField("contentPane");
741 field
.setAccessible(true);
742 field
.set(rootPane
, null);
745 field
= Window
.class.getDeclaredField("windowListener");
746 field
.setAccessible(true);
747 field
.set(this, null);
749 catch (Exception e
) {
753 // http://bugs.sun.com/view_bug.do?bug_id=6614056
755 final Field field
= Dialog
.class.getDeclaredField("modalDialogs");
756 field
.setAccessible(true);
757 final List
<?
> list
= (List
<?
>)field
.get(null);
760 catch (final Exception ex
) {
765 public Component
getMostRecentFocusOwner() {
767 final DialogWrapper wrapper
= getDialogWrapper();
768 if (wrapper
!= null) {
769 JComponent toFocus
= wrapper
.getPreferredFocusedComponent();
770 if (toFocus
!= null) {
775 return super.getMostRecentFocusOwner();
779 public void paint(Graphics g
) {
780 UIUtil
.applyRenderingHints(g
);
784 private class MyWindowListener
extends WindowAdapter
{
785 public void windowClosing(WindowEvent e
) {
786 DialogWrapper dialogWrapper
= getDialogWrapper();
787 if (dialogWrapper
.shouldCloseOnCross()) {
788 dialogWrapper
.doCancelAction(e
);
792 public void windowClosed(WindowEvent e
) {
796 public void saveSize() {
797 if (myDimensionServiceKey
!= null &&
798 myInitialSize
!= null &&
799 myOpened
) { // myInitialSize can be null only if dialog is disposed before first showing
800 final Project projectGuess
= PlatformDataKeys
.PROJECT
.getData(DataManager
.getInstance().getDataContext(MyDialog
.this));
803 Point location
= getLocation();
804 DimensionService
.getInstance().setLocation(myDimensionServiceKey
, location
, projectGuess
);
806 Dimension size
= getSize();
807 if (!myInitialSize
.equals(size
)) {
808 DimensionService
.getInstance().setSize(myDimensionServiceKey
, size
, projectGuess
);
814 public void windowOpened(final WindowEvent e
) {
815 SwingUtilities
.invokeLater(new Runnable() {
818 final DialogWrapper activeWrapper
= getActiveWrapper();
819 if (activeWrapper
== null) {
820 myFocusedCallback
.setRejected();
821 myTypeAheadDone
.setRejected();
825 JComponent toFocus
= activeWrapper
.getPreferredFocusedComponent();
826 if (toFocus
== null) {
827 toFocus
= getRootPane().getDefaultButton();
830 moveMousePointerOnButton(getRootPane().getDefaultButton());
831 setupSelectionOnPreferredComponent(toFocus
);
833 if (toFocus
!= null) {
834 final JComponent toRequest
= toFocus
;
835 SwingUtilities
.invokeLater(new Runnable() {
837 IdeFocusManager
.findInstanceByComponent(e
.getWindow()).requestFocus(toRequest
, true);
838 notifyFocused(activeWrapper
);
842 notifyFocused(activeWrapper
);
848 private void notifyFocused(DialogWrapper wrapper
) {
849 myFocusedCallback
.setDone();
850 final long timeout
= wrapper
.getTypeAheadTimeoutMs();
852 SimpleTimer
.getInstance().setUp(new EdtRunnable() {
853 public void runEdt() {
854 myTypeAheadDone
.setDone();
860 private DialogWrapper
getActiveWrapper() {
861 DialogWrapper activeWrapper
= getDialogWrapper();
862 if (activeWrapper
== null || !activeWrapper
.isShowing()) {
866 return activeWrapper
;
869 private void moveMousePointerOnButton(final JButton button
) {
870 Application application
= ApplicationManager
.getApplication();
871 if (application
!= null && application
.hasComponent(UISettings
.class)) {
872 if (button
!= null && UISettings
.getInstance().MOVE_MOUSE_ON_DEFAULT_BUTTON
) {
873 Point p
= button
.getLocationOnScreen();
874 Rectangle r
= button
.getBounds();
876 Robot robot
= new Robot();
877 robot
.mouseMove(p
.x
+ r
.width
/ 2, p
.y
+ r
.height
/ 2);
879 catch (AWTException exc
) {
880 exc
.printStackTrace();
887 private class MyComponentListener
extends ComponentAdapter
{
888 @SuppressWarnings({"RefusedBequest"})
889 public void componentResized(ComponentEvent e
) {
890 final JRootPane pane
= getRootPane();
891 if (pane
== null) return;
892 final Dimension minSize
= pane
.getMinimumSize();
893 final Dimension size
= pane
.getSize();
894 final Dimension winSize
= getSize();
895 if (minSize
.width
> size
.width
) {
896 winSize
.width
+= minSize
.width
- size
.width
;
898 if (minSize
.height
> size
.height
) {
899 winSize
.height
+= minSize
.height
- size
.height
;
902 if (!winSize
.equals(getSize())) {
903 SwingUtilities
.invokeLater(new Runnable() {
914 private class DialogRootPane
extends JRootPane
implements DataProvider
{
916 private final boolean myGlassPaneIsSet
;
918 private DialogRootPane() {
919 setGlassPane(new IdeGlassPaneImpl(this));
920 myGlassPaneIsSet
= true;
924 public void setGlassPane(final Component glass
) {
925 if (myGlassPaneIsSet
) {
926 LOG
.warn("Setting of glass pane for DialogWrapper is prohibited", new Exception());
930 super.setGlassPane(glass
);
933 public Object
getData(@NonNls String dataId
) {
934 final DialogWrapper wrapper
= myDialogWrapper
.get();
935 return PlatformDataKeys
.UI_DISPOSABLE
.is(dataId
) ? wrapper
.getDisposable() : null;
940 private class MyFocusCommand
extends FocusCommand
implements KeyEventProcessor
{
942 private Context myContextOnFinish
;
943 private ArrayList
<KeyEvent
> myEvents
= new ArrayList
<KeyEvent
>();
944 private DialogWrapper myWrapper
;
946 private MyFocusCommand(DialogWrapper wrapper
) {
947 myWrapper
= getDialogWrapper();
949 Disposer
.register(wrapper
.getDisposable(), new Disposable() {
950 public void dispose() {
951 if (!myTypeAheadDone
.isProcessed()) {
952 myTypeAheadDone
.setDone();
960 public ActionCallback
run() {
961 return myTypeAheadDone
;
965 public KeyEventProcessor
getProcessor() {
969 public Boolean
dispatch(KeyEvent e
, Context context
) {
970 if (myWrapper
== null || myTypeAheadDone
.isProcessed()) return null;
972 myEvents
.addAll(context
.getQueue());
973 context
.getQueue().clear();
975 if (isToDipatchToDialogNow(e
)) {
983 private boolean isToDipatchToDialogNow(KeyEvent e
) {
984 return e
.getKeyCode() == KeyEvent
.VK_ENTER
|| e
.getKeyCode() == KeyEvent
.VK_ESCAPE
|| e
.getKeyCode() == KeyEvent
.VK_TAB
;
987 public void finish(Context context
) {
988 myContextOnFinish
= context
;
991 private void flushEvents() {
992 if (myWrapper
.isToDispatchTypeAhead() && myContextOnFinish
!= null) {
993 myContextOnFinish
.dispatch(myEvents
);
999 private static void setupSelectionOnPreferredComponent(final JComponent component
) {
1000 if (component
instanceof JTextField
) {
1001 JTextField field
= (JTextField
)component
;
1002 String text
= field
.getText();
1003 if (text
!= null && field
.getClientProperty(HAVE_INITIAL_SELECTION
) == null) {
1004 field
.setSelectionStart(0);
1005 field
.setSelectionEnd(text
.length());
1008 else if (component
instanceof JComboBox
) {
1009 JComboBox combobox
= (JComboBox
)component
;
1010 combobox
.getEditor().selectAll();
1014 public void setContentPane(JComponent content
) {
1015 myDialog
.setContentPane(content
);
1018 public void centerInParent() {
1019 myDialog
.centerInParent();