IDEA-35480 Per project/frame modality

This commit is contained in:
Denis Fokin
2013-08-30 19:22:30 +04:00
parent f146f92197
commit 46fb5e87dd
13 changed files with 168 additions and 64 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ public class EditConfigurationsDialog extends SingleConfigurableEditor implement
protected Executor myExecutor;
public EditConfigurationsDialog(final Project project) {
super(project, new RunConfigurable(project));
super(project, new RunConfigurable(project), IdeModalityType.PROJECT);
((RunConfigurable)getConfigurable()).setRunDialog(this);
setTitle(ExecutionBundle.message("run.debug.dialog.title"));
setHorizontalStretch(1.3F);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@ public class RunDialog extends DialogWrapper implements RunConfigurable.RunDialo
public static boolean editConfiguration(final Project project, final RunnerAndConfigurationSettings configuration, final String title, @Nullable final Executor executor) {
final SingleConfigurationConfigurable<RunConfiguration> configurable = SingleConfigurationConfigurable.editSettings(configuration, executor);
final SingleConfigurableEditor dialog = new SingleConfigurableEditor(project, configurable) {
final SingleConfigurableEditor dialog = new SingleConfigurableEditor(project, configurable, IdeModalityType.PROJECT) {
{
if (executor != null) setOKButtonText(executor.getActionName());
if (executor != null) setOKButtonIcon(executor.getIcon());
@@ -73,6 +73,22 @@ import java.util.Set;
*/
@SuppressWarnings({"SSBasedInspection", "MethodMayBeStatic", "UnusedDeclaration"})
public abstract class DialogWrapper {
public static enum IdeModalityType {
IDE,
PROJECT,
MODELESS;
public Dialog.ModalityType toAwtModality () {
switch (this) {
case IDE: return Dialog.ModalityType.APPLICATION_MODAL;
case PROJECT: return Dialog.ModalityType.DOCUMENT_MODAL;
case MODELESS: return Dialog.ModalityType.MODELESS;
}
return null;
}
}
/**
* The default exit code for "OK" action.
*/
@@ -180,7 +196,11 @@ public abstract class DialogWrapper {
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
*/
protected DialogWrapper(@Nullable Project project, boolean canBeParent) {
myPeer = createPeer(project, canBeParent);
this(project, canBeParent, IdeModalityType.IDE);
}
protected DialogWrapper(@Nullable Project project, boolean canBeParent, IdeModalityType ideModalityType) {
myPeer = createPeer(project, canBeParent, ideModalityType);
final Window window = myPeer.getWindow();
if (window != null) {
myResizeListener = new ComponentAdapter() {
@@ -303,16 +323,16 @@ public abstract class DialogWrapper {
myErrorPainter.setValidationInfo(info);
if (! myErrorText.isTextSet(info.message)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myDisposed) return;
setErrorText(info.message);
myPeer.getRootPane().getGlassPane().repaint();
getOKAction().setEnabled(false);
}
});
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (myDisposed) return;
setErrorText(info.message);
myPeer.getRootPane().getGlassPane().repaint();
getOKAction().setEnabled(false);
}
});
}
}
private void installErrorPainter() {
@@ -725,8 +745,17 @@ public abstract class DialogWrapper {
return createPeer(null, canBeParent, applicationModalIfPossible);
}
protected DialogWrapperPeer createPeer(final Window owner, final boolean canBeParent, final IdeModalityType ideModalityType) {
return DialogWrapperPeerFactory.getInstance().createPeer(this, owner, canBeParent, ideModalityType);
}
@Deprecated
protected DialogWrapperPeer createPeer(final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) {
return DialogWrapperPeerFactory.getInstance().createPeer(this, owner, canBeParent, applicationModalIfPossible);
return DialogWrapperPeerFactory.getInstance().createPeer(this, owner, canBeParent, applicationModalIfPossible ? IdeModalityType.IDE : IdeModalityType.PROJECT);
}
protected DialogWrapperPeer createPeer(@Nullable final Project project, final boolean canBeParent, final IdeModalityType ideModalityType) {
return DialogWrapperPeerFactory.getInstance().createPeer(this, project, canBeParent, ideModalityType);
}
protected DialogWrapperPeer createPeer(@Nullable final Project project, final boolean canBeParent) {
@@ -40,10 +40,17 @@ public abstract class DialogWrapperPeerFactory {
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent);
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, boolean canBeParent);
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType);
/** @see DialogWrapper#DialogWrapper(boolean, boolean)
*/
@Deprecated
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, boolean canBeParent, boolean applicationModalIfPossible);
@Deprecated
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, Window owner, boolean canBeParent, boolean applicationModalIfPossible);
@Deprecated
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, @NotNull Component parent, boolean canBeParent);
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType);
public abstract DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, Window owner, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType);
}
@@ -63,7 +63,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
private static void _showSettingsDialog(final Project project, ConfigurableGroup[] group, @Nullable Configurable toSelect) {
group = filterEmptyGroups(group);
if (Registry.is("ide.mac.modalDialogsOnFullscreen")) {
if (Registry.is("ide.perProjectModality")) {
new OptionsEditorDialog(project, group, toSelect, true).show();
} else {
if (Registry.is("ide.new.preferences")) {
@@ -113,7 +113,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
group = filterEmptyGroups(group);
OptionsEditorDialog dialog;
if (Registry.is("ide.mac.modalDialogsOnFullscreen")) {
if (Registry.is("ide.perProjectModality")) {
dialog = new OptionsEditorDialog(actualProject, group, nameToSelect, true);
} else {
dialog = new OptionsEditorDialog(actualProject, group, nameToSelect);
@@ -137,7 +137,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
final Configurable configurable2Select = findConfigurable2Select(id2Select, group);
final OptionsEditorDialog dialog;
if (Registry.is("ide.mac.modalDialogsOnFullscreen")) {
if (Registry.is("ide.perProjectModality")) {
dialog = new OptionsEditorDialog(actualProject, group, configurable2Select, true);
} else {
dialog = new OptionsEditorDialog(actualProject, group, configurable2Select);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,8 +53,9 @@ public class SingleConfigurableEditor extends DialogWrapper {
public SingleConfigurableEditor(@Nullable Project project,
Configurable configurable,
@NonNls String dimensionKey,
final boolean showApplyButton) {
super(project, true);
final boolean showApplyButton,
final IdeModalityType ideModalityType) {
super(project, true, ideModalityType);
myDimensionKey = dimensionKey;
myShowApplyButton = showApplyButton;
setTitle(createTitleString(configurable));
@@ -68,7 +69,8 @@ public class SingleConfigurableEditor extends DialogWrapper {
public SingleConfigurableEditor(Component parent,
Configurable configurable,
String dimensionServiceKey,
final boolean showApplyButton) {
final boolean showApplyButton,
final IdeModalityType ideModalityType) {
super(parent, true);
myDimensionKey = dimensionServiceKey;
myShowApplyButton = showApplyButton;
@@ -80,6 +82,24 @@ public class SingleConfigurableEditor extends DialogWrapper {
myConfigurable.reset();
}
public SingleConfigurableEditor(@Nullable Project project,
Configurable configurable,
@NonNls String dimensionKey,
final boolean showApplyButton) {
this(project, configurable, dimensionKey, showApplyButton, IdeModalityType.IDE);
}
public SingleConfigurableEditor(Component parent,
Configurable configurable,
String dimensionServiceKey,
final boolean showApplyButton) {
this(parent, configurable, dimensionServiceKey, showApplyButton, IdeModalityType.IDE);
}
public SingleConfigurableEditor(@Nullable Project project, Configurable configurable, @NonNls String dimensionKey, IdeModalityType ideModalityType) {
this(project, configurable, dimensionKey, true, ideModalityType);
}
public SingleConfigurableEditor(@Nullable Project project, Configurable configurable, @NonNls String dimensionKey) {
this(project, configurable, dimensionKey, true);
}
@@ -88,6 +108,10 @@ public class SingleConfigurableEditor extends DialogWrapper {
this(parent, configurable, dimensionServiceKey, true);
}
public SingleConfigurableEditor(@Nullable Project project, Configurable configurable, IdeModalityType ideModalityType) {
this(project, configurable, ShowSettingsUtilImpl.createDimensionKey(configurable), ideModalityType);
}
public SingleConfigurableEditor(@Nullable Project project, Configurable configurable) {
this(project, configurable, ShowSettingsUtilImpl.createDimensionKey(configurable));
}
@@ -53,7 +53,7 @@ public class OptionsEditorDialog extends DialogWrapper implements DataProvider{
@NonNls static final String LAST_SELECTED_CONFIGURABLE = "options.lastSelected";
/** This constructor should be eliminated after the new modality approach
* will have been checked. See a {@code Registry} key ide.mac.modalDialogsOnFullscreen
* will have been checked. See a {@code Registry} key ide.perProjectModality
* @deprecated
*/
public OptionsEditorDialog(Project project, ConfigurableGroup[] groups,
@@ -63,7 +63,7 @@ public class OptionsEditorDialog extends DialogWrapper implements DataProvider{
}
/** This constructor should be eliminated after the new modality approach
* will have been checked. See a {@code Registry} key ide.mac.modalDialogsOnFullscreen
* will have been checked. See a {@code Registry} key ide.perProjectModality
* @deprecated
*/
public OptionsEditorDialog(Project project, ConfigurableGroup[] groups,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ interface AbstractDialog extends Disposable {
void addKeyListener(KeyListener listener);
@Deprecated // Use setModalityType instead
void setModal(boolean b);
void toFront();
@@ -87,8 +88,13 @@ interface AbstractDialog extends Disposable {
void setLocation(int x, int y);
@Deprecated // use getModalityTypeInstead
boolean isModal();
void setModalityType(Dialog.ModalityType modalityType);
Dialog.ModalityType getModalityType();
void show();
IdeFocusManager getFocusManager();
@@ -30,6 +30,10 @@ public class DialogWrapperPeerFactoryImpl extends DialogWrapperPeerFactory {
return new DialogWrapperPeerImpl(wrapper, project, canBeParent);
}
public DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType) {
return new DialogWrapperPeerImpl(wrapper, project, canBeParent, ideModalityType);
}
@Override
public DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, boolean canBeParent) {
return new DialogWrapperPeerImpl(wrapper, canBeParent);
@@ -53,4 +57,17 @@ public class DialogWrapperPeerFactoryImpl extends DialogWrapperPeerFactory {
public DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, @NotNull Component parent, boolean canBeParent) {
return new DialogWrapperPeerImpl(wrapper, parent, canBeParent);
}
@Override
public DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType) {
return new DialogWrapperPeerImpl(wrapper, (Window)null, canBeParent, ideModalityType);
}
@Override
public DialogWrapperPeer createPeer(@NotNull DialogWrapper wrapper,
Window owner,
boolean canBeParent,
DialogWrapper.IdeModalityType ideModalityType) {
return new DialogWrapperPeerImpl(wrapper, owner, canBeParent, ideModalityType);
}
}
@@ -77,16 +77,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
private final ActionCallback myTypeAheadDone = new ActionCallback("DialogTypeAheadDone");
private ActionCallback myTypeAheadCallback;
/**
* Creates modal <code>DialogWrapper</code>. The currently active window will be the dialog's parent.
*
* @param project parent window for the dialog will be calculated based on focused window for the
* specified <code>project</code>. This parameter can be <code>null</code>. In this case parent window
* will be suggested based on current focused window.
* @param canBeParent specifies whether the dialog can be parent for other windows. This parameter is used
* by <code>WindowManager</code>.
*/
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent) {
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType) {
myWrapper = wrapper;
myTypeAheadCallback = myWrapper.isTypeAheadEnabled() ? new ActionCallback() : null;
myWindowManager = null;
@@ -135,7 +126,20 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
}
}
createDialog(owner, canBeParent);
createDialog(owner, canBeParent, ideModalityType);
}
/**
* Creates modal <code>DialogWrapper</code>. The currently active window will be the dialog's parent.
*
* @param project parent window for the dialog will be calculated based on focused window for the
* specified <code>project</code>. This parameter can be <code>null</code>. In this case parent window
* will be suggested based on current focused window.
* @param canBeParent specifies whether the dialog can be parent for other windows. This parameter is used
* by <code>WindowManager</code>.
*/
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @Nullable Project project, boolean canBeParent) {
this(wrapper, project, canBeParent, DialogWrapper.IdeModalityType.IDE);
}
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, boolean canBeParent) {
@@ -181,14 +185,8 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
createDialog(owner, canBeParent);
}
/** @see DialogWrapper#DialogWrapper(boolean, boolean)
*/
@Deprecated
public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, final boolean canBeParent, final boolean applicationModalIfPossible) {
this(wrapper, null, canBeParent, applicationModalIfPossible);
}
public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper,final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) {
public DialogWrapperPeerImpl(@NotNull final DialogWrapper wrapper,final Window owner, final boolean canBeParent,
final DialogWrapper.IdeModalityType ideModalityType ) {
myWrapper = wrapper;
myWindowManager = null;
Application application = ApplicationManager.getApplication();
@@ -196,15 +194,28 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
myWindowManager = (WindowManagerEx)WindowManager.getInstance();
}
createDialog(owner, canBeParent);
if (applicationModalIfPossible && !isHeadless()) {
Dialog.ModalityType modalityType = Dialog.ModalityType.TOOLKIT_MODAL;
if (Registry.is("ide.mac.modalDialogsOnFullscreen")) {
modalityType = Dialog.ModalityType.APPLICATION_MODAL;
if (!isHeadless()) {
Dialog.ModalityType modalityType = DialogWrapper.IdeModalityType.IDE.toAwtModality();
if (Registry.is("ide.perProjectModality")) {
modalityType = ideModalityType.toAwtModality();
}
((MyDialog)myDialog).setModalityType(modalityType);
myDialog.setModalityType(modalityType);
}
}
/** @see DialogWrapper#DialogWrapper(boolean, boolean)
*/
@Deprecated
public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, final boolean canBeParent, final boolean applicationModalIfPossible) {
this(wrapper, null, canBeParent, applicationModalIfPossible);
}
@Deprecated
public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper,final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) {
this(wrapper, owner, canBeParent, applicationModalIfPossible ? DialogWrapper.IdeModalityType.IDE : DialogWrapper.IdeModalityType.PROJECT);
}
@Override
public void setUndecorated(boolean undecorated) {
myDialog.setUndecorated(undecorated);
@@ -225,19 +236,22 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
myDialog.addKeyListener(listener);
}
private void createDialog(@Nullable Window owner, boolean canBeParent) {
private void createDialog(@Nullable Window owner, boolean canBeParent, DialogWrapper.IdeModalityType ideModalityType) {
if (isHeadless()) {
myDialog = new HeadlessDialog();
return;
}
myDialog = new MyDialog(owner, myWrapper, myProject, myWindowFocusedCallback, myTypeAheadDone, myTypeAheadCallback);
if (!Registry.is("ide.mac.modalDialogsOnFullscreen")) {
myDialog.setModal(true);
}
myDialog.setModalityType(ideModalityType.toAwtModality());
myCanBeParent = canBeParent;
}
private void createDialog(@Nullable Window owner, boolean canBeParent) {
createDialog(owner, canBeParent, DialogWrapper.IdeModalityType.IDE);
}
@Override
public void toFront() {
myDialog.toFront();
@@ -546,10 +560,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
@NotNull ActionCallback typeAheadDone,
ActionCallback typeAheadCallback) {
super(owner);
if (Registry.is("ide.mac.modalDialogsOnFullscreen")) {
//todo should be passed in the super method
setModalityType(ModalityType.DOCUMENT_MODAL);
}
myDialogWrapper = new WeakReference<DialogWrapper>(dialogWrapper);
myProject = project != null ? new WeakReference<Project>(project) : null;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,6 +131,15 @@ class HeadlessDialog implements AbstractDialog {
return false;
}
@Override
public void setModalityType(Dialog.ModalityType modalityType) {
}
@Override
public Dialog.ModalityType getModalityType() {
return null;
}
public void show() {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.impl.commands.FinalizableCommand;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -78,7 +79,8 @@ public final class CommandProcessor implements Runnable {
// definitely have some since runnables in command list may (and do) request some PSI activity
final boolean queueNext = myCommandCount > 0;
Application application = ApplicationManager.getApplication();
application.getInvokator().invokeLater(command, ModalityState.NON_MODAL, expire == null ? application.getDisposed() : expire).doWhenDone(new Runnable() {
ModalityState modalityState = Registry.is("ide.perProjectModality") ? ModalityState.defaultModalityState() : ModalityState.NON_MODAL;
application.getInvokator().invokeLater(command, modalityState, expire == null ? application.getDisposed() : expire).doWhenDone(new Runnable() {
public void run() {
if (queueNext) {
CommandProcessor.this.run();
@@ -131,9 +131,9 @@ ide.mac.hide.cursor.when.typing=true
ide.mac.show.native.help=true
ide.mac.useNativeClipboard=false
ide.mac.boldEditorTabs=false
ide.mac.modalDialogsOnFullscreen=false
ide.perProjectModality=false
# suppress inspection "UnusedProperty"
ide.mac.modalDialogsOnFullscreen.description=New modality approach. All dialogs are DOCUMENT_MODAL expect ide-wide dialogs
ide.perProjectModality.description=New modality approach. All dialogs are DOCUMENT_MODAL expect ide-wide dialogs
ide.mac.retina.disableDrawingFix=false
@@ -318,4 +318,4 @@ GRADLE.system.in.process=true
# suppress inspection "UnusedProperty"
GRADLE.system.in.process.description=Whether IDEA should use 'in-process' mode for interaction with gradle api
grails.advanced.mode=false
grails.advanced.mode=false