summaryrefslogtreecommitdiff
path: root/platform/platform-impl/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'platform/platform-impl/src/com')
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/ErrorReportConfigurable.java29
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java28
-rw-r--r--platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java63
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ide/UiActivityMonitorImpl.java170
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actionMacro/EditMacrosDialog.java37
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actionMacro/actions/EditMacrosAction.java21
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java41
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java11
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java117
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/OpenProjectFileChooserDescriptor.java87
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java115
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java108
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java17
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java22
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java65
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java24
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java57
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form43
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java2
-rw-r--r--platform/platform-impl/src/com/intellij/idea/IdeaApplication.java18
-rw-r--r--platform/platform-impl/src/com/intellij/notification/impl/actions/ShowDelayedMessageInternalAction.java58
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java786
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java68
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java47
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java23
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java40
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java25
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java187
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java81
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java53
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java26
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFiles.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFolders.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtMergeFiles.java54
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/EditorPlaceHolder.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java66
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java26
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java22
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/ContextMenuImpl.java25
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java55
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java34
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java37
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java54
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java244
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/CompositeConfigurable.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java98
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java31
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java54
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java52
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java52
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java75
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java16
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java330
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java442
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java78
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.form41
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.java159
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java211
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java182
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java134
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectMacrosUtil.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java24
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java8
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java16
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.form4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AppUIUtil.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ui/EditorTextField.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ui/FocusTrackback.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java15
-rw-r--r--platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java10
-rwxr-xr-xplatform/platform-impl/src/com/intellij/ui/messages/SheetController.java4
-rwxr-xr-xplatform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java6
114 files changed, 3318 insertions, 2182 deletions
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ErrorReportConfigurable.java b/platform/platform-impl/src/com/intellij/diagnostic/ErrorReportConfigurable.java
index 7d5688c9d1d8..3f865dd19abd 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/ErrorReportConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/ErrorReportConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -21,17 +21,11 @@ import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
-import org.apache.commons.codec.binary.Base64;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.Base64;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
-/**
- * Created by IntelliJ IDEA.
- * User: stathik
- * Date: Aug 11, 2003
- * Time: 8:59:04 PM
- * To change this template use Options | File Templates.
- */
public class ErrorReportConfigurable implements JDOMExternalizable, NamedComponent {
public String ITN_LOGIN = "";
public String ITN_PASSWORD_CRYPT = "";
@@ -43,31 +37,36 @@ public class ErrorReportConfigurable implements JDOMExternalizable, NamedCompone
return ServiceManager.getService(ErrorReportConfigurable.class);
}
+ @Override
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
- if (! KEEP_ITN_PASSWORD)
+ if (!KEEP_ITN_PASSWORD) {
ITN_PASSWORD_CRYPT = "";
+ }
}
+ @Override
public void writeExternal(Element element) throws WriteExternalException {
String itnPassword = ITN_PASSWORD_CRYPT;
- if (! KEEP_ITN_PASSWORD)
+ if (!KEEP_ITN_PASSWORD) {
ITN_PASSWORD_CRYPT = "";
+ }
DefaultJDOMExternalizer.writeExternal(this, element);
ITN_PASSWORD_CRYPT = itnPassword;
}
+ @Override
@NotNull
public String getComponentName() {
return "ErrorReportConfigurable";
}
- public String getPlainItnPassword () {
- return new String(new Base64().decode(ErrorReportConfigurable.getInstance().ITN_PASSWORD_CRYPT.getBytes()));
+ public String getPlainItnPassword() {
+ return new String(Base64.decode(getInstance().ITN_PASSWORD_CRYPT), CharsetToolkit.UTF8_CHARSET);
}
- public void setPlainItnPassword (String password) {
- ITN_PASSWORD_CRYPT = new String(new Base64().encode(password.getBytes()));
+ public void setPlainItnPassword(String password) {
+ ITN_PASSWORD_CRYPT = Base64.encode(password.getBytes(CharsetToolkit.UTF8_CHARSET));
}
}
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
index 092c346d40b7..fb34ba2342cf 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -19,32 +19,25 @@ import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.ClickListener;
-import com.intellij.util.net.HTTPProxySettingsDialog;
+import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
-/**
- * Created by IntelliJ IDEA.
- * User: stathik
- * Date: Aug 8, 2003
- * Time: 3:49:50 PM
- * To change this template use Options | File Templates.
- */
public class JetBrainsAccountDialog extends DialogWrapper {
private JTextField myItnLoginTextField;
private JPasswordField myItnPasswordTextField;
private JCheckBox myRememberITNPasswordCheckBox;
- public void storeInfo () {
+ public void storeInfo() {
ErrorReportConfigurable.getInstance().ITN_LOGIN = myItnLoginTextField.getText();
ErrorReportConfigurable.getInstance().setPlainItnPassword(new String(myItnPasswordTextField.getPassword()));
ErrorReportConfigurable.getInstance().KEEP_ITN_PASSWORD = myRememberITNPasswordCheckBox.isSelected();
}
- public void loadInfo () {
+ public void loadInfo() {
myItnLoginTextField.setText(ErrorReportConfigurable.getInstance().ITN_LOGIN);
myItnPasswordTextField.setText(ErrorReportConfigurable.getInstance().getPlainItnPassword());
myRememberITNPasswordCheckBox.setSelected(ErrorReportConfigurable.getInstance().KEEP_ITN_PASSWORD);
@@ -64,6 +57,7 @@ public class JetBrainsAccountDialog extends DialogWrapper {
protected JLabel mySendingSettingsLabel;
private JLabel myCreateAccountLabel;
+ @Override
protected String getDimensionServiceKey() {
return "#com.intellij.diagnostic.AbstractSendErrorDialog";
}
@@ -73,6 +67,7 @@ public class JetBrainsAccountDialog extends DialogWrapper {
return myItnLoginTextField;
}
+ @Override
protected void init() {
setTitle(ReportMessages.ERROR_REPORT);
getContentPane().add(myMainPanel);
@@ -80,14 +75,12 @@ public class JetBrainsAccountDialog extends DialogWrapper {
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
- HTTPProxySettingsDialog settingsDialog = new HTTPProxySettingsDialog ();
- settingsDialog.pack();
- settingsDialog.show();
+ HttpConfigurable.editConfigurable(myMainPanel);
return true;
}
}.installOn(mySendingSettingsLabel);
- mySendingSettingsLabel.setCursor(new Cursor (Cursor.HAND_CURSOR));
+ mySendingSettingsLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
loadInfo();
@@ -98,9 +91,9 @@ public class JetBrainsAccountDialog extends DialogWrapper {
return true;
}
}.installOn(myCreateAccountLabel);
- myCreateAccountLabel.setCursor(new Cursor (Cursor.HAND_CURSOR));
+ myCreateAccountLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
- super.init ();
+ super.init();
}
@Override
@@ -109,6 +102,7 @@ public class JetBrainsAccountDialog extends DialogWrapper {
super.doOKAction();
}
+ @Override
protected JComponent createCenterPanel() {
return myMainPanel;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
index 0aeb20dbda90..c288150bd7ab 100644
--- a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
+++ b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -137,7 +137,9 @@ public class CommandLineProcessor {
if (args.size() > 0) {
String command = args.get(0);
for(ApplicationStarter starter: Extensions.getExtensions(ApplicationStarter.EP_NAME)) {
- if (starter instanceof ApplicationStarterEx && command.equals(starter.getCommandName())) {
+ if (command.equals(starter.getCommandName()) &&
+ starter instanceof ApplicationStarterEx &&
+ ((ApplicationStarterEx)starter).canProcessExternalCommandLine()) {
LOG.info("Processing command with " + starter);
((ApplicationStarterEx) starter).processExternalCommandLine(ArrayUtil.toStringArray(args));
return null;
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
index a7d07c9fa1e8..23491c2bdd6a 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -130,9 +130,9 @@ public class IdeEventQueue extends EventQueue {
private final Set<EventDispatcher> myDispatchers = new LinkedHashSet<EventDispatcher>();
- private final Set<EventDispatcher> myPostprocessors = new LinkedHashSet<EventDispatcher>();
-
+ private final Set<EventDispatcher> myPostProcessors = new LinkedHashSet<EventDispatcher>();
private final Set<Runnable> myReady = new HashSet<Runnable>();
+
private boolean myKeyboardBusy;
private boolean myDispatchingFocusEvent;
@@ -148,16 +148,14 @@ public class IdeEventQueue extends EventQueue {
private IdeEventQueue() {
addIdleTimeCounterRequest();
- final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- //noinspection HardCodedStringLiteral
+ final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
keyboardFocusManager.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
@Override
public void propertyChange(final PropertyChangeEvent e) {
final Application application = ApplicationManager.getApplication();
if (application == null) {
-
// We can get focus event before application is initialized
return;
}
@@ -171,6 +169,12 @@ public class IdeEventQueue extends EventQueue {
});
addDispatcher(new WindowsAltSupressor(), null);
+
+ Application app = ApplicationManager.getApplication();
+ if (app != null && app.isUnitTestMode()) {
+ //noinspection AssignmentToStaticFieldFromInstanceMethod
+ ourAppIsLoaded = true;
+ }
}
@@ -289,11 +293,11 @@ public class IdeEventQueue extends EventQueue {
}
public void addPostprocessor(EventDispatcher dispatcher, @Nullable Disposable parent) {
- _addProcessor(dispatcher, parent, myPostprocessors);
+ _addProcessor(dispatcher, parent, myPostProcessors);
}
public void removePostprocessor(EventDispatcher dispatcher) {
- myPostprocessors.remove(dispatcher);
+ myPostProcessors.remove(dispatcher);
}
private static void _addProcessor(final EventDispatcher dispatcher, Disposable parent, final Set<EventDispatcher> set) {
@@ -344,8 +348,26 @@ public class IdeEventQueue extends EventQueue {
}
}
+ private static boolean ourAppIsLoaded = false;
+
+ private static boolean appIsLoaded() {
+ if (ourAppIsLoaded) return true;
+ boolean loaded = IdeaApplication.isLoaded();
+ if (loaded) ourAppIsLoaded = true;
+ return loaded;
+ }
+
@Override
public void dispatchEvent(AWTEvent e) {
+ if (!appIsLoaded()) {
+ try {
+ super.dispatchEvent(e);
+ }
+ catch (Throwable t) {
+ processException(t);
+ }
+ return;
+ }
fixNonEnglishKeyboardLayouts(e);
@@ -362,15 +384,13 @@ public class IdeEventQueue extends EventQueue {
_dispatchEvent(e, false);
}
catch (Throwable t) {
- if (!myToolkitBugsProcessor.process(t)) {
- PluginManager.processException(t);
- }
+ processException(t);
}
finally {
myIsInInputEvent = wasInputEvent;
myCurrentEvent = oldEvent;
- for (EventDispatcher each : myPostprocessors) {
+ for (EventDispatcher each : myPostProcessors) {
each.dispatch(e);
}
@@ -380,6 +400,12 @@ public class IdeEventQueue extends EventQueue {
}
}
+ private void processException(Throwable t) {
+ if (!myToolkitBugsProcessor.process(t)) {
+ PluginManager.processException(t);
+ }
+ }
+
private static void fixNonEnglishKeyboardLayouts(AWTEvent e) {
if (!Registry.is("ide.non.english.keyboard.layout.fix")) return;
if (e instanceof KeyEvent) {
@@ -722,9 +748,7 @@ public class IdeEventQueue extends EventQueue {
super.dispatchEvent(e);
}
catch (Throwable t) {
- if (!myToolkitBugsProcessor.process(t)) {
- PluginManager.processException(t);
- }
+ processException(t);
}
finally {
myDispatchingFocusEvent = false;
@@ -760,7 +784,7 @@ public class IdeEventQueue extends EventQueue {
}
private static boolean typeAheadDispatchToFocusManager(AWTEvent e) {
- if (e instanceof KeyEvent && appIsLoaded()) {
+ if (e instanceof KeyEvent) {
final KeyEvent event = (KeyEvent)e;
if (!event.isConsumed()) {
final IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(event.getComponent());
@@ -771,15 +795,6 @@ public class IdeEventQueue extends EventQueue {
return false;
}
- private static boolean ourAppIsLoaded = false;
-
- private static boolean appIsLoaded() {
- if (ourAppIsLoaded) return true;
- boolean loaded = IdeaApplication.isLoaded();
- if (loaded) ourAppIsLoaded = true;
- return loaded;
- }
-
public void flushQueue() {
while (true) {
AWTEvent event = peekEvent();
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
index d7118949e5de..4a0e11bf5ff9 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
@@ -128,19 +128,23 @@ public class IdeRepaintManager extends RepaintManager {
final Exception exception = new Exception();
StackTraceElement[] stackTrace = exception.getStackTrace();
for (StackTraceElement st : stackTrace) {
- if (repaint && st.getClassName().startsWith("javax.swing.")) {
+ String className = st.getClassName();
+ String methodName = st.getMethodName();
+
+ if (repaint && className.startsWith("javax.swing.")) {
fromSwing = true;
}
- if (repaint && "imageUpdate".equals(st.getMethodName())) {
+ if (repaint && "imageUpdate".equals(methodName)) {
swingKnownNonAwtOperations = true;
}
- if (st.getClassName().startsWith("javax.swing.JEditorPane") && st.getMethodName().equals("read")) {
+ if ("read".equals(methodName) && className.startsWith("javax.swing.JEditorPane") ||
+ "setCharacterAttributes".equals(methodName) && className.startsWith("javax.swing.text.DefaultStyledDocument")) {
swingKnownNonAwtOperations = true;
break;
}
- if ("repaint".equals(st.getMethodName())) {
+ if ("repaint".equals(methodName)) {
repaint = true;
fromSwing = false;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/UiActivityMonitorImpl.java b/platform/platform-impl/src/com/intellij/ide/UiActivityMonitorImpl.java
index c25c68b4bb2b..e9de64905415 100644
--- a/platform/platform-impl/src/com/intellij/ide/UiActivityMonitorImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/UiActivityMonitorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -16,7 +16,6 @@
package com.intellij.ide;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ModalityStateListener;
@@ -24,7 +23,6 @@ import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.BusyObject;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -34,16 +32,16 @@ import javax.swing.*;
import java.util.*;
public class UiActivityMonitorImpl extends UiActivityMonitor implements ModalityStateListener, Disposable {
-
private final FactoryMap<Project, BusyContainer> myObjects = new FactoryMap<Project, BusyContainer>() {
@Override
protected BusyContainer create(Project key) {
if (isEmpty()) {
installListener();
}
- return key == null ? new BusyContainer(key) : new BusyContainer(null) {
+ return key == null ? new BusyContainer(null) : new BusyContainer(null) {
+ @NotNull
@Override
- protected BusyImpl createBusyImpl(HashSet<UiActivity> key) {
+ protected BusyImpl createBusyImpl(@NotNull Set<UiActivity> key) {
return new BusyImpl(key, this) {
@Override
public boolean isReady() {
@@ -63,7 +61,8 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
private boolean myActive;
- private BusyObject myEmptyBusy = new BusyObject.Impl() {
+ @NotNull
+ private final BusyObject myEmptyBusy = new BusyObject.Impl() {
@Override
public boolean isReady() {
return true;
@@ -84,17 +83,12 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
@Override
public void beforeModalityStateChanged(boolean entering) {
- if (isUnitTestMode()) {
- maybeReady();
- }
- else {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- maybeReady();
- }
- });
- }
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ maybeReady();
+ }
+ });
}
public void maybeReady() {
@@ -103,15 +97,17 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
}
}
+ @NotNull
@Override
- public BusyObject getBusy(@NotNull Project project, UiActivity... toWatch) {
+ public BusyObject getBusy(@NotNull Project project, @NotNull UiActivity... toWatch) {
if (!isActive()) return myEmptyBusy;
return _getBusy(project, toWatch);
}
+ @NotNull
@Override
- public BusyObject getBusy(UiActivity... toWatch) {
+ public BusyObject getBusy(@NotNull UiActivity... toWatch) {
if (!isActive()) return myEmptyBusy;
return _getBusy(null, toWatch);
@@ -129,10 +125,10 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
if (!isActive()) return;
- invokeLaterIfNeeded(new MyRunnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void run(Throwable allocation) {
- getBusyContainer(project).addActivity(activity, allocation, effectiveModalityState);
+ public void run() {
+ getBusyContainer(project).addActivity(activity, effectiveModalityState);
}
});
}
@@ -141,9 +137,9 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
public void removeActivity(@NotNull final Project project, @NotNull final UiActivity activity) {
if (!isActive()) return;
- invokeLaterIfNeeded(new MyRunnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void run(Throwable allocation) {
+ public void run() {
_getBusy(project).removeActivity(activity);
}
});
@@ -162,10 +158,10 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
public void addActivity(@NotNull final UiActivity activity, @NotNull final ModalityState effectiveModalityState) {
if (!isActive()) return;
- invokeLaterIfNeeded(new MyRunnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void run(Throwable allocation) {
- getBusyContainer(null).addActivity(activity, allocation, effectiveModalityState);
+ public void run() {
+ getBusyContainer(null).addActivity(activity, effectiveModalityState);
}
});
}
@@ -174,15 +170,16 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
public void removeActivity(@NotNull final UiActivity activity) {
if (!isActive()) return;
- invokeLaterIfNeeded(new MyRunnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void run(Throwable allocation) {
+ public void run() {
_getBusy(null).removeActivity(activity);
}
});
}
- private BusyImpl _getBusy(@Nullable Project key, UiActivity... toWatch) {
+ @NotNull
+ private BusyImpl _getBusy(@Nullable Project key, @NotNull UiActivity... toWatch) {
return getBusyContainer(key).getOrCreateBusy(toWatch);
}
@@ -204,6 +201,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
return myObjects.get(null);
}
+ @Override
public void clear() {
final Set<Project> keys = myObjects.keySet();
for (Project each : keys) {
@@ -215,7 +213,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
public void setActive(boolean active) {
if (myActive == active) return;
- if (myActive && !active) {
+ if (myActive) {
clear();
}
@@ -227,25 +225,19 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
}
private static class ActivityInfo {
- private final Throwable myAllocation;
private final ModalityState myEffectiveState;
- private ActivityInfo(@Nullable Throwable allocation, @NotNull ModalityState effectiveState) {
- myAllocation = allocation;
+ private ActivityInfo(@NotNull ModalityState effectiveState) {
myEffectiveState = effectiveState;
}
- @Nullable
- public Throwable getAllocation() {
- return myAllocation;
- }
-
@NotNull
public ModalityState getEffectiveState() {
return myEffectiveState;
}
}
+ @NotNull
protected ModalityState getCurrentState() {
return ModalityState.current();
}
@@ -258,9 +250,9 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
protected final Set<UiActivity> myToWatch;
protected final UiActivity[] myToWatchArray;
- private UiActivityMonitorImpl.BusyContainer myContainer;
+ private final UiActivityMonitorImpl.BusyContainer myContainer;
- private BusyImpl(Set<UiActivity> toWatch, BusyContainer container) {
+ private BusyImpl(@NotNull Set<UiActivity> toWatch, @NotNull BusyContainer container) {
myToWatch = toWatch;
myToWatchArray = toWatch.toArray(new UiActivity[toWatch.size()]);
myContainer = container;
@@ -274,9 +266,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
boolean isOwnReady() {
Map<UiActivity, ActivityInfo> infoToCheck = new HashMap<UiActivity, ActivityInfo>();
- final Iterator<Set<UiActivity>> activitySets = myContainer.myActivities2Object.keySet().iterator();
- while (activitySets.hasNext()) {
- Set<UiActivity> eachActivitySet = activitySets.next();
+ for (Set<UiActivity> eachActivitySet : myContainer.myActivities2Object.keySet()) {
final BusyImpl eachBusyObject = myContainer.myActivities2Object.get(eachActivitySet);
if (eachBusyObject == this) continue;
@@ -304,19 +294,16 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
return true;
}
+ public void addActivity(@NotNull UiActivity activity, @NotNull ModalityState effectiveModalityState) {
+ if (!myToWatch.isEmpty() && !myToWatch.contains(activity)) return;
- public void addActivity(UiActivity activity, Throwable allocation, ModalityState effectiveModalityState) {
- if (!myToWatch.isEmpty()) {
- if (!myToWatch.contains(activity)) return;
- }
-
- myActivities.put(activity, new ActivityInfo(allocation, effectiveModalityState));
+ myActivities.put(activity, new ActivityInfo(effectiveModalityState));
myQueuedToRemove.remove(activity);
- myContainer.onActivityAdded(this, activity);
+ myContainer.onActivityAdded(activity);
}
- public void removeActivity(final UiActivity activity) {
+ public void removeActivity(@NotNull final UiActivity activity) {
if (!myActivities.containsKey(activity)) return;
myQueuedToRemove.add(activity);
@@ -333,87 +320,48 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
onReady();
}
};
- if (isUnitTestMode()) {
- runnable.run();
- }
- else {
- SwingUtilities.invokeLater(runnable);
- }
+ SwingUtilities.invokeLater(runnable);
}
-
- public void clear() {
- UiActivity[] activities = myActivities.keySet().toArray(new UiActivity[myActivities.size()]);
- for (UiActivity each : activities) {
- removeActivity(each);
- }
- }
- }
-
- private static void invokeLaterIfNeeded(final MyRunnable runnable) {
- final Throwable allocation = Registry.is("ide.debugMode") ? new Exception() : null;
-
- if (isUnitTestMode()) {
- runnable.run(allocation);
- }
- else {
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- runnable.run(allocation);
- }
- });
- }
- }
-
- private interface MyRunnable {
- void run(Throwable allocation);
- }
-
- private static boolean isUnitTestMode() {
- Application app = ApplicationManager.getApplication();
- return app == null || app.isUnitTestMode();
}
public class BusyContainer implements Disposable {
+ private final Map<Set<UiActivity>, BusyImpl> myActivities2Object = new HashMap<Set<UiActivity>, BusyImpl>();
+ private final Map<BusyImpl, Set<UiActivity>> myObject2Activities = new HashMap<BusyImpl, Set<UiActivity>>();
- private Map<Set<UiActivity>, BusyImpl> myActivities2Object = new HashMap<Set<UiActivity>, BusyImpl>();
- private Map<BusyImpl, Set<UiActivity>> myObject2Activities = new HashMap<BusyImpl, Set<UiActivity>>();
-
- private Set<UiActivity> myActivities = new HashSet<UiActivity>();
-
- private BusyImpl myDefault;
+ private final Set<UiActivity> myActivities = new HashSet<UiActivity>();
private boolean myRemovingActivityNow;
@Nullable private final Project myProject;
public BusyContainer(@Nullable Project project) {
myProject = project;
- myDefault = registerBusyObject(new HashSet<UiActivity>());
+ registerBusyObject(new HashSet<UiActivity>());
if (project != null) {
Disposer.register(project, this);
}
}
- public BusyImpl getOrCreateBusy(UiActivity... activities) {
- final HashSet<UiActivity> key = new HashSet<UiActivity>();
+ @NotNull
+ public BusyImpl getOrCreateBusy(@NotNull UiActivity... activities) {
+ Set<UiActivity> key = new HashSet<UiActivity>();
key.addAll(Arrays.asList(activities));
if (myActivities2Object.containsKey(key)) {
return myActivities2Object.get(key);
}
- else {
- return registerBusyObject(key);
- }
+ return registerBusyObject(key);
}
- private BusyImpl registerBusyObject(HashSet<UiActivity> key) {
+ @NotNull
+ private BusyImpl registerBusyObject(@NotNull Set<UiActivity> key) {
final BusyImpl busy = createBusyImpl(key);
myActivities2Object.put(key, busy);
myObject2Activities.put(busy, key);
return busy;
}
- protected BusyImpl createBusyImpl(HashSet<UiActivity> key) {
+ @NotNull
+ protected BusyImpl createBusyImpl(@NotNull Set<UiActivity> key) {
return new BusyImpl(key, this);
}
@@ -437,11 +385,11 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
}
}
- public void onActivityAdded(BusyImpl busy, UiActivity activity) {
+ public void onActivityAdded(@NotNull UiActivity activity) {
myActivities.add(activity);
}
- public void onActivityRemoved(BusyImpl busy, UiActivity activity) {
+ public void onActivityRemoved(@NotNull BusyImpl busy, @NotNull UiActivity activity) {
if (myRemovingActivityNow) return;
final Map<BusyImpl, Set<UiActivity>> toRemove = new HashMap<BusyImpl, Set<UiActivity>>();
@@ -450,9 +398,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
myRemovingActivityNow = true;
myActivities.remove(activity);
- final Iterator<BusyImpl> objects = myObject2Activities.keySet().iterator();
- while (objects.hasNext()) {
- BusyImpl each = objects.next();
+ for (BusyImpl each : myObject2Activities.keySet()) {
if (each != busy) {
each.removeActivity(activity);
}
@@ -472,11 +418,11 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
}
}
- public void addActivity(UiActivity activity, Throwable allocation, ModalityState state) {
+ public void addActivity(@NotNull UiActivity activity, @NotNull ModalityState state) {
getOrCreateBusy(activity);
final Set<BusyImpl> busies = myObject2Activities.keySet();
for (BusyImpl each : busies) {
- each.addActivity(activity, allocation, state);
+ each.addActivity(activity, state);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/EditMacrosDialog.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/EditMacrosDialog.java
deleted file mode 100644
index 8b2c9acfaef5..000000000000
--- a/platform/platform-impl/src/com/intellij/ide/actionMacro/EditMacrosDialog.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2000-2009 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.actionMacro;
-
-import com.intellij.openapi.options.ex.SingleConfigurableEditor;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Jul 22, 2003
- * Time: 3:30:56 PM
- * To change this template use Options | File Templates.
- */
-public class EditMacrosDialog extends SingleConfigurableEditor {
- public EditMacrosDialog(@Nullable Project project) {
- super(project, new ActionMacroConfigurable());
- }
-
- protected String getDimensionServiceKey(){
- return "#com.intellij.ide.actionMacro.EditMacrosDialog";
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/actions/EditMacrosAction.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/actions/EditMacrosAction.java
index cb0d0ffd4619..c46241d1c4d9 100644
--- a/platform/platform-impl/src/com/intellij/ide/actionMacro/actions/EditMacrosAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/actions/EditMacrosAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -16,29 +16,22 @@
package com.intellij.ide.actionMacro.actions;
import com.intellij.ide.actionMacro.ActionMacro;
+import com.intellij.ide.actionMacro.ActionMacroConfigurable;
import com.intellij.ide.actionMacro.ActionMacroManager;
-import com.intellij.ide.actionMacro.EditMacrosDialog;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.DumbAware;
-/**
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Jul 22, 2003
- * Time: 3:33:04 PM
- * To change this template use Options | File Templates.
- */
public class EditMacrosAction extends AnAction implements DumbAware {
+ @Override
public void actionPerformed(AnActionEvent e) {
- EditMacrosDialog dialog = new EditMacrosDialog(CommonDataKeys.PROJECT.getData(e.getDataContext()));
- dialog.show();
+ ShowSettingsUtil.getInstance().editConfigurable(e.getProject(), "#com.intellij.ide.actionMacro.EditMacrosDialog", new ActionMacroConfigurable());
}
+ @Override
public void update(AnActionEvent e) {
- final ActionMacroManager manager = ActionMacroManager.getInstance();
- ActionMacro[] macros = manager.getAllMacros();
+ ActionMacro[] macros = ActionMacroManager.getInstance().getAllMacros();
e.getPresentation().setEnabled(macros != null && macros.length > 0);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java
index 1c7855d2eedb..709c3b458112 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseNavigateToSourceAction.java
@@ -19,7 +19,9 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.Navigatable;
import com.intellij.pom.NavigatableWithText;
+import com.intellij.pom.PomTargetPsiElement;
import com.intellij.util.OpenSourceUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class BaseNavigateToSourceAction extends AnAction implements DumbAware {
@@ -37,7 +39,7 @@ public abstract class BaseNavigateToSourceAction extends AnAction implements Dum
public void update(AnActionEvent event) {
DataContext dataContext = event.getDataContext();
- final Navigatable target = getTarget(dataContext);
+ final Navigatable target = findTargetForUpdate(dataContext);
boolean enabled = target != null;
if (ActionPlaces.isPopupPlace(event.getPlace())) {
event.getPresentation().setVisible(enabled);
@@ -49,36 +51,21 @@ public abstract class BaseNavigateToSourceAction extends AnAction implements Dum
else {
event.getPresentation().setEnabled(enabled);
}
- if (target != null && target instanceof NavigatableWithText) {
- //as myFocusEditor is always ignored - Main Menu|View always contains 2 actions with the same name and actually same behaviour
- if (!myFocusEditor) {
- event.getPresentation().setVisible(false);
- return;
- }
- final String navigateActionText = ((NavigatableWithText)target).getNavigateActionText(myFocusEditor);
- if (navigateActionText != null) {
- event.getPresentation().setText(navigateActionText);
- }
- else {
- event.getPresentation().setText(getTemplatePresentation().getText());
- }
- }
- else {
- event.getPresentation().setText(getTemplatePresentation().getText());
- }
+ //as myFocusEditor is always ignored - Main Menu|View always contains 2 actions with the same name and actually same behaviour
+ event.getPresentation().setVisible(target == null || myFocusEditor);
+ String navigateActionText = myFocusEditor && target instanceof NavigatableWithText?
+ ((NavigatableWithText)target).getNavigateActionText(true) : null;
+ event.getPresentation().setText(navigateActionText == null ? getTemplatePresentation().getText() : navigateActionText);
}
@Nullable
- private Navigatable getTarget(final DataContext dataContext) {
- if (!myFocusEditor && CommonDataKeys.EDITOR.getData(dataContext) != null) {
- // makes no sense in editor and conflicts with another action there (ctrl+enter)
- return null;
- }
-
+ private Navigatable findTargetForUpdate(@NotNull DataContext dataContext) {
Navigatable[] navigatables = getNavigatables(dataContext);
- if (navigatables != null) {
- for (Navigatable navigatable : navigatables) {
- if (navigatable.canNavigate()) return navigatable;
+ if (navigatables == null) return null;
+
+ for (Navigatable navigatable : navigatables) {
+ if (navigatable.canNavigate()) {
+ return navigatable instanceof PomTargetPsiElement ? ((PomTargetPsiElement)navigatable).getTarget() : navigatable;
}
}
return null;
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
index 9bdc5948cffe..136f4b166e1a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
@@ -23,6 +23,7 @@ import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -104,11 +105,15 @@ public class CreateDesktopEntryAction extends DumbAwareAction {
final String message = ApplicationBundle.message("desktop.entry.success",
ApplicationNamesInfo.getInstance().getProductName());
- Notifications.Bus.notify(
- new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Desktop entry created", message, NotificationType.INFORMATION)
- );
+ if (ApplicationManager.getApplication() != null) {
+ Notifications.Bus
+ .notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Desktop entry created", message, NotificationType.INFORMATION));
+ }
}
catch (Exception e) {
+ if (ApplicationManager.getApplication() == null) {
+ throw new RuntimeException(e);
+ }
final String message = e.getMessage();
if (!StringUtil.isEmptyOrSpaces(message)) {
LOG.warn(e);
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
index 4cabfe9b5fe9..37b09394dd89 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -19,14 +19,14 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileElement;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileChooser.PathChooserDialog;
import com.intellij.openapi.fileChooser.impl.FileChooserUtil;
import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorProvider;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
import com.intellij.openapi.fileTypes.FileType;
@@ -34,7 +34,6 @@ import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -47,54 +46,20 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class OpenFileAction extends AnAction implements DumbAware {
+ @Override
public void actionPerformed(AnActionEvent e) {
- @Nullable final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
+ final Project project = e.getProject();
final boolean showFiles = project != null || PlatformProjectOpenProcessor.getInstanceIfItExists() != null;
+ final FileChooserDescriptor descriptor = showFiles ? new ProjectOrFileChooserDescriptor() : new ProjectOnlyFileChooserDescriptor();
+ descriptor.putUserData(PathChooserDialog.PREFER_LAST_OVER_EXPLICIT, showFiles);
- final FileChooserDescriptor descriptor = new OpenProjectFileChooserDescriptor(true) {
- @Override
- public boolean isFileSelectable(VirtualFile file) {
- if (super.isFileSelectable(file)) {
- return true;
- }
- if (file.isDirectory()) {
- return false;
- }
- return showFiles && !FileElement.isArchive(file);
- }
-
- @Override
- public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
- if (!file.isDirectory() && isFileSelectable(file)) {
- if (!showHiddenFiles && FileElement.isFileHidden(file)) return false;
- return true;
- }
- return super.isFileVisible(file, showHiddenFiles);
- }
-
- @Override
- public boolean isChooseMultiple() {
- return showFiles;
- }
- };
- descriptor.setTitle(showFiles ? "Open File or Project" : "Open Project");
-
- VirtualFile userHomeDir = null;
- if (SystemInfo.isUnix) {
- userHomeDir = VfsUtil.getUserHomeDir();
- }
-
- descriptor.putUserData(PathChooserDialog.PREFER_LAST_OVER_EXPLICIT, Boolean.TRUE);
-
- FileChooser.chooseFiles(descriptor, project, userHomeDir, new Consumer<List<VirtualFile>>() {
+ FileChooser.chooseFiles(descriptor, project, VfsUtil.getUserHomeDir(), new Consumer<List<VirtualFile>>() {
@Override
public void consume(final List<VirtualFile> files) {
for (VirtualFile file : files) {
- if (!descriptor.isFileSelectable(file)) { // on Mac, it could be selected anyway
- Messages.showInfoMessage(project,
- file.getPresentableUrl() + " contains no " +
- ApplicationNamesInfo.getInstance().getFullProductName() + " project",
- "Cannot Open Project");
+ if (!descriptor.isFileSelectable(file)) {
+ String message = IdeBundle.message("error.dir.contains.no.project", file.getPresentableUrl());
+ Messages.showInfoMessage(project, message, IdeBundle.message("title.cannot.open.project"));
return;
}
}
@@ -103,9 +68,8 @@ public class OpenFileAction extends AnAction implements DumbAware {
});
}
- private static void doOpenFile(@Nullable final Project project,
- @NotNull final List<VirtualFile> result) {
- for (final VirtualFile file : result) {
+ private static void doOpenFile(@Nullable Project project, @NotNull List<VirtualFile> result) {
+ for (VirtualFile file : result) {
if (file.isDirectory()) {
Project openedProject;
if (ProjectAttachProcessor.canAttachToProject()) {
@@ -118,9 +82,8 @@ public class OpenFileAction extends AnAction implements DumbAware {
return;
}
- if (OpenProjectFileChooserDescriptor.isProjectFile(file) &&
- // if the ipr-based project is already open, just open the ipr file
- (project == null || !file.equals(project.getProjectFile()))) {
+ // try to open as a project - unless the file is an .ipr of the current one
+ if ((project == null || !file.equals(project.getProjectFile())) && OpenProjectFileChooserDescriptor.isProjectFile(file)) {
Project openedProject = ProjectUtil.openOrImport(file.getPath(), project, false);
if (openedProject != null) {
FileChooserUtil.setLastOpenedFile(openedProject, file);
@@ -143,26 +106,54 @@ public class OpenFileAction extends AnAction implements DumbAware {
}
}
- public static void openFile(final String filePath, final Project project) {
- final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(filePath);
+ public static void openFile(String filePath, @NotNull Project project) {
+ VirtualFile file = LocalFileSystem.getInstance().findFileByPath(filePath);
if (file != null && file.isValid()) {
openFile(file, project);
}
}
- public static void openFile(final VirtualFile virtualFile, final Project project) {
- FileEditorProviderManager editorProviderManager = FileEditorProviderManager.getInstance();
- if (editorProviderManager.getProviders(project, virtualFile).length == 0) {
- Messages.showMessageDialog(project,
- IdeBundle.message("error.files.of.this.type.cannot.be.opened",
- ApplicationNamesInfo.getInstance().getProductName()),
- IdeBundle.message("title.cannot.open.file"),
- Messages.getErrorIcon());
+ public static void openFile(VirtualFile file, @NotNull Project project) {
+ FileEditorProvider[] providers = FileEditorProviderManager.getInstance().getProviders(project, file);
+ if (providers.length == 0) {
+ String message = IdeBundle.message("error.files.of.this.type.cannot.be.opened", ApplicationNamesInfo.getInstance().getProductName());
+ Messages.showErrorDialog(project, message, IdeBundle.message("title.cannot.open.file"));
return;
}
- OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile);
+ OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
}
+ private static class ProjectOnlyFileChooserDescriptor extends OpenProjectFileChooserDescriptor {
+ public ProjectOnlyFileChooserDescriptor() {
+ super(true);
+ setTitle(IdeBundle.message("title.open.project"));
+ }
+ }
+
+ // vanilla OpenProjectFileChooserDescriptor only accepts project files; this on is overridden to accept any files
+ private static class ProjectOrFileChooserDescriptor extends OpenProjectFileChooserDescriptor {
+ private final FileChooserDescriptor myStandardDescriptor = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
+
+ public ProjectOrFileChooserDescriptor() {
+ super(true);
+ setTitle(IdeBundle.message("title.open.file.or.project"));
+ }
+
+ @Override
+ public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+ return file.isDirectory() ? super.isFileVisible(file, showHiddenFiles) : myStandardDescriptor.isFileVisible(file, showHiddenFiles);
+ }
+
+ @Override
+ public boolean isFileSelectable(VirtualFile file) {
+ return file.isDirectory() ? super.isFileSelectable(file) : myStandardDescriptor.isFileSelectable(file);
+ }
+
+ @Override
+ public boolean isChooseMultiple() {
+ return true;
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OpenProjectFileChooserDescriptor.java b/platform/platform-impl/src/com/intellij/ide/actions/OpenProjectFileChooserDescriptor.java
index 51d6362b36d8..b462fcbc11ad 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OpenProjectFileChooserDescriptor.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OpenProjectFileChooserDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -15,74 +15,91 @@
*/
package com.intellij.ide.actions;
-import com.intellij.icons.AllIcons;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.projectImport.ProjectOpenProcessor;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
+/**
+ * Intended for use in actions related to opening or importing existing projects.
+ * <strong>Due to a high I/O impact SHOULD NOT be used in any other cases.</strong>
+ */
public class OpenProjectFileChooserDescriptor extends FileChooserDescriptor {
private static final Icon ourProjectIcon = IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getSmallIconUrl());
- public OpenProjectFileChooserDescriptor(final boolean chooseFiles) {
+ public OpenProjectFileChooserDescriptor(boolean chooseFiles) {
super(chooseFiles, true, chooseFiles, chooseFiles, false, false);
}
- public boolean isFileSelectable(final VirtualFile file) {
- if (file == null) return false;
+ @Override
+ public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+ return super.isFileVisible(file, showHiddenFiles) && (file.isDirectory() || isProjectFile(file));
+ }
+
+ @Override
+ public boolean isFileSelectable(VirtualFile file) {
return isProjectDirectory(file) || isProjectFile(file);
}
- public Icon getIcon(final VirtualFile file) {
- if (isProjectDirectory(file)) {
- return dressIcon(file, ourProjectIcon);
- }
- final Icon icon = getImporterIcon(file);
- if (icon != null) {
- return dressIcon(file, icon);
+ @Override
+ public Icon getIcon(VirtualFile file) {
+ if (canInspectDirectory(file)) {
+ if (isIprFile(file) || isIdeaDirectory(file)) {
+ return dressIcon(file, ourProjectIcon);
+ }
+ Icon icon = getImporterIcon(file);
+ if (icon != null) {
+ return dressIcon(file, icon);
+ }
}
return super.getIcon(file);
}
- @Nullable
- private static Icon getImporterIcon(final VirtualFile virtualFile) {
- final ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(virtualFile);
+ private static boolean canInspectDirectory(VirtualFile file) {
+ if (file.getParent() == null) return false;
+
+ VirtualFile home = VfsUtil.getUserHomeDir();
+ if (home == null) return false; // unnatural situation
+ VirtualFile homes = home.getParent();
+ if (homes == null) return false; // another one
+ if (homes.equals(file.getParent()) || VfsUtilCore.isAncestor(file, homes, false)) return false;
+
+ return true;
+ }
+
+ private static Icon getImporterIcon(VirtualFile file) {
+ ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(file);
if (provider != null) {
- return virtualFile.isDirectory() && provider.lookForProjectsInDirectory() ? AllIcons.Nodes.IdeaModule : provider.getIcon(virtualFile);
+ return file.isDirectory() && provider.lookForProjectsInDirectory() ? ourProjectIcon : provider.getIcon(file);
}
return null;
}
- public boolean isFileVisible(final VirtualFile file, final boolean showHiddenFiles) {
- if (!showHiddenFiles && FileElement.isFileHidden(file)) return false;
- return isProjectFile(file) || super.isFileVisible(file, showHiddenFiles) && file.isDirectory();
+ public static boolean isProjectFile(@NotNull VirtualFile file) {
+ return !file.isDirectory() && file.isValid() && (isIprFile(file) || hasImportProvider(file));
}
- public static boolean isProjectFile(final VirtualFile file) {
- if (isIprFile(file)) return true;
- final ProjectOpenProcessor importProvider = ProjectOpenProcessor.getImportProvider(file);
- return importProvider != null;
+ private static boolean isProjectDirectory(@NotNull VirtualFile file) {
+ return file.isDirectory() && file.isValid() && (isIdeaDirectory(file) || hasImportProvider(file));
}
private static boolean isIprFile(VirtualFile file) {
- if ((!file.isDirectory() && file.getName().toLowerCase().endsWith(ProjectFileType.DOT_DEFAULT_EXTENSION))) {
- return true;
- }
- return false;
+ return ProjectFileType.DEFAULT_EXTENSION.equalsIgnoreCase(file.getExtension());
+ }
+
+ private static boolean isIdeaDirectory(VirtualFile file) {
+ return file.findChild(Project.DIRECTORY_STORE_FOLDER) != null;
}
- private static boolean isProjectDirectory(final VirtualFile virtualFile) {
- // the root directory of any drive is never an IDEA project
- if (virtualFile.getParent() == null) return false;
- // NOTE: For performance reasons, it's very important not to iterate through all of the children here.
- if (virtualFile.isDirectory() && virtualFile.isValid() && virtualFile.findChild(Project.DIRECTORY_STORE_FOLDER) != null) return true;
- return false;
+ private static boolean hasImportProvider(VirtualFile file) {
+ return ProjectOpenProcessor.getImportProvider(file) != null;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
index 4df11f7261ca..2c5cc5b02282 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
@@ -15,23 +15,20 @@
*/
package com.intellij.ide.actions;
+import com.intellij.ide.ui.search.SearchUtil;
+import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurableGroup;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.options.ShowSettingsUtil;
-import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil;
-import com.intellij.openapi.options.ex.IdeConfigurablesGroup;
-import com.intellij.openapi.options.ex.MixedConfigurableGroup;
-import com.intellij.openapi.options.ex.ProjectConfigurablesGroup;
-import com.intellij.openapi.options.ex.SingleConfigurableEditor;
+import com.intellij.openapi.options.*;
+import com.intellij.openapi.options.ex.*;
+import com.intellij.openapi.options.newEditor.IdeSettingsDialog;
import com.intellij.openapi.options.newEditor.OptionsEditor;
import com.intellij.openapi.options.newEditor.OptionsEditorDialog;
-import com.intellij.openapi.options.newEditor.PreferencesDialog;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.navigation.Place;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NotNull;
@@ -47,7 +44,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class ShowSettingsUtilImpl extends ShowSettingsUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowSettingsUtilImpl");
- private AtomicBoolean myShown = new AtomicBoolean(false);
+ private final AtomicBoolean myShown = new AtomicBoolean(false);
@NotNull
private static Project getProject(@Nullable Project project) {
@@ -55,12 +52,16 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
}
@NotNull
- private static DialogWrapper getDialog(@Nullable Project project, @NotNull ConfigurableGroup[] groups, @Nullable Configurable toSelect) {
+ public static DialogWrapper getDialog(@Nullable Project project, @NotNull ConfigurableGroup[] groups, @Nullable Configurable toSelect) {
+ project = getProject(project);
+ final ConfigurableGroup[] filteredGroups = filterEmptyGroups(groups);
+ if (Registry.is("ide.new.settings.dialog")) {
+ return new IdeSettingsDialog(project, filteredGroups, toSelect);
+ }
+ //noinspection deprecation
return Registry.is("ide.perProjectModality")
- ? new OptionsEditorDialog(getProject(project), filterEmptyGroups(groups), toSelect, true)
- : Registry.is("ide.new.preferences")
- ? new PreferencesDialog(getProject(project), filterEmptyGroups(groups))
- : new OptionsEditorDialog(getProject(project), filterEmptyGroups(groups), toSelect);
+ ? new OptionsEditorDialog(project, filteredGroups, toSelect, true)
+ : new OptionsEditorDialog(project, filteredGroups, toSelect);
}
@NotNull
@@ -73,7 +74,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
new ProjectConfigurablesGroup(project),
new IdeConfigurablesGroup()};
- return Registry.is("ide.file.settings.order.new")
+ return Registry.is("ide.new.settings.dialog")
? MixedConfigurableGroup.getGroups(getConfigurables(groups, true))
: groups;
}
@@ -139,41 +140,34 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
@Override
public void showSettingsDialog(@Nullable final Project project, @NotNull final String nameToSelect) {
- ConfigurableGroup[] group = getConfigurableGroups(project, true);
-
+ ConfigurableGroup[] groups = getConfigurableGroups(project, true);
Project actualProject = getProject(project);
- group = filterEmptyGroups(group);
+ groups = filterEmptyGroups(groups);
+ getDialog(actualProject, groups, findPreselectedByDisplayName(nameToSelect, groups)).show();
+ }
- OptionsEditorDialog dialog;
- if (Registry.is("ide.perProjectModality")) {
- dialog = new OptionsEditorDialog(actualProject, group, nameToSelect, true);
- }
- else {
- dialog = new OptionsEditorDialog(actualProject, group, nameToSelect);
+ @Nullable
+ private static Configurable findPreselectedByDisplayName(final String preselectedConfigurableDisplayName, ConfigurableGroup[] groups) {
+ final List<Configurable> all = SearchUtil.expand(groups);
+ for (Configurable each : all) {
+ if (preselectedConfigurableDisplayName.equals(each.getDisplayName())) return each;
}
- dialog.show();
+ return null;
}
public static void showSettingsDialog(@Nullable Project project, final String id2Select, final String filter) {
ConfigurableGroup[] group = getConfigurableGroups(project, true);
- Project actualProject = getProject(project);
-
group = filterEmptyGroups(group);
final Configurable configurable2Select = findConfigurable2Select(id2Select, group);
- final OptionsEditorDialog dialog;
- if (Registry.is("ide.perProjectModality")) {
- dialog = new OptionsEditorDialog(actualProject, group, configurable2Select, true);
- } else {
- dialog = new OptionsEditorDialog(actualProject, group, configurable2Select);
- }
+ final DialogWrapper dialog = getDialog(project, group, configurable2Select);
new UiNotifyConnector.Once(dialog.getContentPane(), new Activatable.Adapter() {
@Override
public void showNotify() {
- final OptionsEditor editor = (OptionsEditor)dialog.getData(OptionsEditor.KEY.getName());
+ final OptionsEditor editor = (OptionsEditor)((DataProvider)dialog).getData(OptionsEditor.KEY.getName());
LOG.assertTrue(editor != null);
editor.select(configurable2Select, filter);
}
@@ -234,37 +228,53 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
@Override
public <T extends Configurable> T findProjectConfigurable(final Project project, final Class<T> confClass) {
+ //noinspection deprecation
return ConfigurableExtensionPointUtil.findProjectConfigurable(project, confClass);
}
@Override
public boolean editConfigurable(Project project, String dimensionServiceKey, @NotNull Configurable configurable) {
- return editConfigurable(null, project, configurable, dimensionServiceKey, null);
+ return editConfigurable(project, dimensionServiceKey, configurable, isWorthToShowApplyButton(configurable));
+ }
+
+ private static boolean isWorthToShowApplyButton(@NotNull Configurable configurable) {
+ return configurable instanceof Place.Navigator ||
+ configurable instanceof Composite ||
+ configurable instanceof TabbedConfigurable;
+ }
+
+ @Override
+ public boolean editConfigurable(Project project, String dimensionServiceKey, @NotNull Configurable configurable, boolean showApplyButton) {
+ return editConfigurable(null, project, configurable, dimensionServiceKey, null, showApplyButton);
}
@Override
public boolean editConfigurable(Project project, Configurable configurable, Runnable advancedInitialization) {
- return editConfigurable(null, project, configurable, createDimensionKey(configurable), advancedInitialization);
+ return editConfigurable(null, project, configurable, createDimensionKey(configurable), advancedInitialization, isWorthToShowApplyButton(configurable));
}
@Override
- public boolean editConfigurable(Component parent, Configurable configurable) {
+ public boolean editConfigurable(@Nullable Component parent, @NotNull Configurable configurable) {
return editConfigurable(parent, configurable, null);
}
@Override
- public boolean editConfigurable(final Component parent, final Configurable configurable, @Nullable final Runnable advancedInitialization) {
- return editConfigurable(parent, null, configurable, createDimensionKey(configurable), advancedInitialization);
+ public boolean editConfigurable(@Nullable Component parent, @NotNull Configurable configurable, @Nullable Runnable advancedInitialization) {
+ return editConfigurable(parent, null, configurable, createDimensionKey(configurable), advancedInitialization, isWorthToShowApplyButton(configurable));
}
- private static boolean editConfigurable(final @Nullable Component parent, @Nullable Project project, final Configurable configurable, final String dimensionKey,
- @Nullable final Runnable advancedInitialization) {
- SingleConfigurableEditor editor;
- if (parent != null) {
- editor = new SingleConfigurableEditor(parent, configurable, dimensionKey);
+ private static boolean editConfigurable(@Nullable Component parent,
+ @Nullable Project project,
+ @NotNull Configurable configurable,
+ String dimensionKey,
+ @Nullable final Runnable advancedInitialization,
+ boolean showApplyButton) {
+ final SingleConfigurableEditor editor;
+ if (parent == null) {
+ editor = new SingleConfigurableEditor(project, configurable, dimensionKey, showApplyButton);
}
else {
- editor = new SingleConfigurableEditor(project, configurable, dimensionKey);
+ editor = new SingleConfigurableEditor(parent, configurable, dimensionKey, showApplyButton);
}
if (advancedInitialization != null) {
new UiNotifyConnector.Once(editor.getContentPane(), new Activatable.Adapter() {
@@ -278,15 +288,14 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
return editor.isOK();
}
- public static String createDimensionKey(Configurable configurable) {
- String displayName = configurable.getDisplayName();
- displayName = displayName.replaceAll("\n", "_").replaceAll(" ", "_");
- return "#" + displayName;
+ @NotNull
+ public static String createDimensionKey(@NotNull Configurable configurable) {
+ return '#' + StringUtil.replaceChar(StringUtil.replaceChar(configurable.getDisplayName(), '\n', '_'), ' ', '_');
}
@Override
- public boolean editConfigurable(Component parent, String dimensionServiceKey,Configurable configurable) {
- return editConfigurable(parent, null, configurable, dimensionServiceKey, null);
+ public boolean editConfigurable(Component parent, String dimensionServiceKey, Configurable configurable) {
+ return editConfigurable(parent, null, configurable, dimensionServiceKey, null, isWorthToShowApplyButton(configurable));
}
public boolean isAlreadyShown() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java
index a9461422f747..825db992b218 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ViewSourceAction.java
@@ -17,9 +17,21 @@
package com.intellij.ide.actions;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
public class ViewSourceAction extends BaseNavigateToSourceAction {
public ViewSourceAction() {
super(false);
}
+
+ @Override
+ public void update(AnActionEvent e) {
+ if (CommonDataKeys.EDITOR.getData(e.getDataContext()) != null) {
+ e.getPresentation().setEnabledAndVisible(false);
+ }
+ else {
+ super.update(e);
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java b/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java
index 6844ed5bab25..798247e16186 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/AbstractCustomizeWizardStep.java
@@ -21,12 +21,14 @@ import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
+import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
public abstract class AbstractCustomizeWizardStep extends JPanel {
+ protected static final int SMALL_GAP = 10;
protected static final int GAP = 20;
protected abstract String getTitle();
@@ -40,6 +42,14 @@ public abstract class AbstractCustomizeWizardStep extends JPanel {
return ColorUtil.mix(UIUtil.getListSelectionBackground(), UIUtil.getLabelBackground(), UIUtil.isUnderDarcula() ? .5 : .75);
}
+ public static Border createSmallEmptyBorder() {
+ return BorderFactory.createEmptyBorder(SMALL_GAP, SMALL_GAP, SMALL_GAP, SMALL_GAP);
+ }
+
+ public static BorderLayout createSmallBorderLayout() {
+ return new BorderLayout(SMALL_GAP, SMALL_GAP);
+ }
+
protected static JPanel createBigButtonPanel(LayoutManager layout, final JToggleButton anchorButton, final Runnable action) {
final JPanel panel = new JPanel(layout) {
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java
new file mode 100644
index 000000000000..57b68232b797
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeDesktopEntryStep.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.customize;
+
+import com.intellij.ide.actions.CreateDesktopEntryAction;
+import com.intellij.idea.ActionsBundle;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.util.EmptyRunnable;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.util.ui.GridBag;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.*;
+
+/**
+ * @author Alexander Lobas
+ */
+public class CustomizeDesktopEntryStep extends AbstractCustomizeWizardStep {
+ private final JCheckBox myCreateEntryCheckBox = new JCheckBox(ActionsBundle.message("action.CreateDesktopEntry.description"));
+ private final JCheckBox myGlobalEntryCheckBox = new JCheckBox("For all users");
+
+ public CustomizeDesktopEntryStep(String iconPath) {
+ setLayout(new BorderLayout());
+
+ JPanel panel = createBigButtonPanel(createSmallBorderLayout(), myCreateEntryCheckBox, EmptyRunnable.INSTANCE);
+ panel.setBorder(createSmallEmptyBorder());
+
+ JPanel buttonPanel = new JPanel(new GridBagLayout());
+ buttonPanel.setOpaque(false);
+
+ GridBag gbc =
+ new GridBag().setDefaultAnchor(GridBagConstraints.WEST).setDefaultFill(GridBagConstraints.HORIZONTAL).setDefaultWeightX(1);
+
+ myCreateEntryCheckBox.setOpaque(false);
+ buttonPanel.add(myCreateEntryCheckBox, gbc.nextLine());
+
+ myGlobalEntryCheckBox.setOpaque(false);
+ gbc.nextLine().insets.left = UIUtil.PANEL_REGULAR_INSETS.left;
+ buttonPanel.add(myGlobalEntryCheckBox, gbc);
+
+ panel.add(buttonPanel, BorderLayout.NORTH);
+
+ JLabel label = new JLabel(IconLoader.getIcon(iconPath));
+ label.setVerticalAlignment(JLabel.TOP);
+ panel.add(label, BorderLayout.CENTER);
+
+ add(panel, BorderLayout.CENTER);
+
+ myCreateEntryCheckBox.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ myGlobalEntryCheckBox.setEnabled(myCreateEntryCheckBox.isSelected());
+ myGlobalEntryCheckBox.setSelected(myCreateEntryCheckBox.isSelected() && !PathManager.getHomePath().startsWith("/home"));
+ }
+ });
+
+ myCreateEntryCheckBox.setSelected(true);
+ }
+
+ public static boolean isAvailable() {
+ return CreateDesktopEntryAction.isAvailable();
+ }
+
+ @Override
+ public boolean beforeOkAction() {
+ if (myCreateEntryCheckBox.isSelected()) {
+ try {
+ CreateDesktopEntryAction.createDesktopEntry(null, new EmptyProgressIndicator(), myGlobalEntryCheckBox.isSelected());
+ }
+ catch (Throwable e) {
+ // ignored
+ }
+ }
+ return true;
+ }
+
+ @Override
+ protected String getTitle() {
+ return "Desktop Entry";
+ }
+
+ @Override
+ protected String getHTMLHeader() {
+ return "<html><body><h2>Create Desktop Entry</h2>&nbsp;</body></html>";
+ }
+
+ @Override
+ protected String getHTMLFooter() {
+ return "Desktop entry can be created later in Tools | Create Desktop Entry...";
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
index 786a5825e783..498391b8e971 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
@@ -18,7 +18,9 @@ package com.intellij.ide.customize;
import com.intellij.CommonBundle;
import com.intellij.icons.AllIcons;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.plugins.PluginNode;
+import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
@@ -78,7 +80,7 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
final String pluginId = s.substring(j + 1);
IdeaPluginDescriptor foundDescriptor = null;
for (IdeaPluginDescriptor descriptor : pluginsFromRepository) {
- if (descriptor.getPluginId().getIdString().equals(pluginId)) {
+ if (descriptor.getPluginId().getIdString().equals(pluginId) && !PluginManagerCore.isBrokenPlugin(descriptor)) {
foundDescriptor = descriptor;
isEmptyOrOffline = false;
break;
@@ -107,11 +109,11 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
JPanel progressPanel = new JPanel(new VerticalFlowLayout(true, false));
progressPanel.add(progressBar);
final LinkLabel cancelLink = new LinkLabel("Cancel", AllIcons.Actions.Cancel);
- JPanel linkWrapper = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ JPanel linkWrapper = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
linkWrapper.add(cancelLink);
progressPanel.add(linkWrapper);
- JPanel buttonPanel = new JPanel(new VerticalFlowLayout());
+ JPanel buttonPanel = new JPanel(new VerticalFlowLayout(0, 0));
buttonPanel.add(installButton);
buttonWrapper.add(buttonPanel, "button");
@@ -218,7 +220,7 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
}, null);
gbc.insets.bottom = -5;
groupPanel.add(titleLabel, gbc);
- gbc.insets.bottom = 10;
+ gbc.insets.bottom = SMALL_GAP;
groupPanel.add(topicLabel, gbc);
groupPanel.add(descriptionLabel, gbc);
gbc.weighty = 1;
@@ -238,7 +240,7 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
protected Color getColor() {
return ColorUtil.withAlpha(JBColor.foreground(), .2);
}
- }, BorderFactory.createEmptyBorder(GAP, GAP, 0, GAP)));
+ }, BorderFactory.createEmptyBorder(0, SMALL_GAP, 0, SMALL_GAP)));
cursor++;
}
@@ -260,7 +262,10 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
@Override
public String getHTMLFooter() {
- return "New plugins can also be downloaded in " + CommonBundle.settingsTitle() + " | Plugins";
+ return "New plugins can also be downloaded in "
+ + CommonBundle.settingsTitle()
+ + " | " + OptionsBundle.message("configurable.group.appearance.settings.display.name")
+ + " | " + "Plugins";
}
public static class OfflineException extends Exception {};
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
index be37f9d9d7f6..af3c193ca9d9 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
@@ -21,7 +21,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.JBCardLayout;
-import org.jetbrains.annotations.NotNull;
+import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -51,6 +51,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
public CustomizeIDEWizardDialog() {
super(null, true, true);
setTitle("Customize " + ApplicationNamesInfo.getInstance().getProductName());
+ getPeer().setAppIcons();
initSteps();
mySkipButton.addActionListener(this);
myBackButton.addActionListener(this);
@@ -119,7 +120,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
result.add(myContentPanel, BorderLayout.CENTER);
result.add(myFooterLabel, BorderLayout.SOUTH);
result.setPreferredSize(new Dimension(700, 600));
- result.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ result.setBorder(AbstractCustomizeWizardStep.createSmallEmptyBorder());
return result;
}
@@ -131,8 +132,10 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
- buttonPanel.add(mySkipButton, gbc);
- gbc.gridx++;
+ if (!PlatformUtils.isCLion()) {
+ buttonPanel.add(mySkipButton, gbc);
+ gbc.gridx++;
+ }
buttonPanel.add(myBackButton, gbc);
gbc.gridx++;
gbc.weightx = 1;
@@ -219,15 +222,4 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
}
myNavigationLabel.setText(navHTML.toString());
}
-
-
- private static <T extends Component> void getChildren(@NotNull Component c, Class<? extends T> cls, List<T> accumulator) {
- if (cls.isAssignableFrom(c.getClass())) accumulator.add((T)c);
- if (c instanceof Container) {
- Component[] components = ((Container)c).getComponents();
- for (Component component : components) {
- getChildren(component, cls, accumulator);
- }
- }
- }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
index 8924c09780dd..de12269b5887 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
@@ -115,7 +115,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
gbc.weighty = 1;
groupPanel.add(Box.createVerticalGlue(), gbc);
gbc.weighty = 0;
- JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
+ JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, SMALL_GAP, SMALL_GAP / 2));
buttonsPanel.setOpaque(false);
if (pluginGroups.getSets(group).size() == 1) {
buttonsPanel.add(createLink(SWITCH_COMMAND + ":" + group, getGroupSwitchTextProvider(group)));
@@ -139,7 +139,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
protected Color getColor() {
return ColorUtil.withAlpha(JBColor.foreground(), .2);
}
- }, BorderFactory.createEmptyBorder(GAP / 2, GAP, GAP / 2, GAP)));
+ }, BorderFactory.createEmptyBorder(SMALL_GAP, GAP, SMALL_GAP, GAP)));
cursor++;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
index b369e49f8bca..c7b29ef53827 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
@@ -22,6 +22,7 @@ import com.intellij.ide.ui.laf.darcula.DarculaLaf;
import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
import com.intellij.idea.StartupUtil;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.IconUtil;
@@ -46,7 +47,7 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
private Map<String, Icon> myLafNames = new LinkedHashMap<String, Icon>();
public CustomizeUIThemeStepPanel() {
- setLayout(new BorderLayout(10, 10));
+ setLayout(createSmallBorderLayout());
IconLoader.activate();
initLafs();
@@ -65,13 +66,13 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
radioButton.setSelected(true);
myDefaultLafName = lafName;
}
- final JPanel panel = createBigButtonPanel(new BorderLayout(10, 10), radioButton, new Runnable() {
+ final JPanel panel = createBigButtonPanel(createSmallBorderLayout(), radioButton, new Runnable() {
@Override
public void run() {
applyLaf(lafName, CustomizeUIThemeStepPanel.this);
}
});
- panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ panel.setBorder(createSmallEmptyBorder());
panel.add(radioButton, myColumnMode ? BorderLayout.WEST : BorderLayout.NORTH);
final JLabel label = new JLabel(myColumnMode ? IconUtil.scale(IconUtil.cropIcon(icon, icon.getIconWidth() * 2 / 3, icon.getIconHeight() * 2 / 3), .5) : icon);
label.setVerticalAlignment(SwingConstants.TOP);
@@ -139,7 +140,10 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
@Override
public String getHTMLFooter() {
- return "UI theme can be changed later in " + CommonBundle.settingsTitle() + " | Appearance";
+ return "UI theme can be changed later in " +
+ CommonBundle.settingsTitle()
+ + " | " + OptionsBundle.message("configurable.group.appearance.settings.display.name")
+ + " | " + "Appearance";
}
private void applyLaf(String lafName, Component component) {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
index 6b0b9814698b..de5d67b5e2d8 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
@@ -15,6 +15,8 @@
*/
package com.intellij.ide.passwordSafe.impl.providers.masterKey;
+import com.intellij.concurrency.AsyncFutureFactory;
+import com.intellij.concurrency.AsyncFutureResult;
import com.intellij.ide.passwordSafe.MasterPasswordUnavailableException;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed;
@@ -23,14 +25,11 @@ import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil;
import com.intellij.ide.passwordSafe.impl.providers.masterKey.windows.WindowsCryptUtils;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,6 +37,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
/**
* The password safe that stores information in configuration file encrypted by master password
@@ -170,12 +170,6 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
}
- if (myDatabase.isEmpty()) {
- if (!MasterPasswordDialog.resetMasterPasswordDialog(project, this, requestor).showAndGet()) {
- throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database.");
- }
- }
-
key = invokeAndWait(new ThrowableComputable<Object, PasswordSafeException>() {
@Override
public Object compute() throws PasswordSafeException {
@@ -184,7 +178,14 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
return key;
}
try {
- MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor);
+ if (myDatabase.isEmpty()) {
+ if (!MasterPasswordDialog.resetMasterPasswordDialog(project, MasterKeyPasswordSafe.this, requestor).showAndGet()) {
+ throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database.");
+ }
+ }
+ else {
+ MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor);
+ }
}
catch (PasswordSafeException e) {
myKey.get().set(e);
@@ -200,35 +201,41 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
private static final Object ourEDTLock = new Object();
- public <T, E extends Throwable> T invokeAndWait(@NotNull final ThrowableComputable<T, E> computable, @NotNull final Condition expired) throws E {
+ public <T, E extends Throwable> T invokeAndWait(@NotNull final ThrowableComputable<T, E> computable, @NotNull final Condition<?> expired) throws E {
if (ApplicationManager.getApplication().isDispatchThread()) {
return computable.compute();
}
- final Ref<Throwable> exRef = Ref.create();
- final Ref<T> ref = Ref.create();
+
+ final AsyncFutureResult<Object> future = AsyncFutureFactory.getInstance().createAsyncFutureResult();
synchronized (ourEDTLock) {
- if (expired.value(null)) {
- throw new ProcessCanceledException();
- }
- ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+ IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(new ExpirableRunnable() {
@Override
- public void run() {
- if (expired.value(null)) {
- exRef.set(new ProcessCanceledException());
- return;
- }
+ public boolean isExpired() {
+ boolean b = expired.value(null);
+ if (b) future.setException(new ProcessCanceledException());
+ return b;
+ }
+ @Override
+ public void run() {
try {
- ref.set(computable.compute());
+ future.set(computable.compute());
}
catch (Throwable e) {
- exRef.set(e);
+ future.setException(e);
}
}
- }, ModalityState.any());
+ });
+ }
+ try {
+ return (T)future.get();
+ }
+ catch (InterruptedException e) {
+ throw new ProcessCanceledException(e);
+ }
+ catch (ExecutionException e) {
+ throw (E) e.getCause();
}
- if (!exRef.isNull()) throw (E)exRef.get();
- return ref.get();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java
index 62609d9ba5fc..0ae246d41715 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java
@@ -29,7 +29,7 @@ import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.TableUtil;
-import com.intellij.util.net.HTTPProxySettingsDialog;
+import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NotNull;
@@ -41,6 +41,7 @@ import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.TreeSet;
/**
@@ -50,7 +51,7 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
public static final String MANAGE_REPOSITORIES = "Manage repositories...";
public static final String N_A = "N/A";
- private PluginManagerMain installed;
+ private final PluginManagerMain installed;
private final String myVendorFilter;
public AvailablePluginsManagerMain(PluginManagerMain installed, PluginManagerUISettings uiSettings, String vendorFilter) {
@@ -63,11 +64,11 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
manageRepositoriesBtn.setMnemonic('m');
manageRepositoriesBtn.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(ActionEvent e) {
+ public void actionPerformed(@NotNull ActionEvent e) {
if (ShowSettingsUtil.getInstance().editConfigurable(myActionsPanel, new PluginHostsConfigurable())) {
final ArrayList<String> pluginHosts = UpdateSettings.getInstance().myPluginHosts;
if (!pluginHosts.contains(((AvailablePluginsTableModel)pluginsModel).getRepository())) {
- ((AvailablePluginsTableModel)pluginsModel).setRepository(AvailablePluginsTableModel.ALL, myFilter.getFilter().toLowerCase());
+ ((AvailablePluginsTableModel)pluginsModel).setRepository(AvailablePluginsTableModel.ALL, myFilter.getFilter().toLowerCase(Locale.ENGLISH));
}
loadAvailablePlugins();
}
@@ -78,11 +79,9 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
final JButton httpProxySettingsButton = new JButton(IdeBundle.message("button.http.proxy.settings"));
httpProxySettingsButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- HTTPProxySettingsDialog settingsDialog = new HTTPProxySettingsDialog();
- settingsDialog.pack();
- settingsDialog.show();
- if (settingsDialog.isOK()) {
+ @Override
+ public void actionPerformed(@NotNull ActionEvent e) {
+ if (HttpConfigurable.editConfigurable(getMainPanel())) {
loadAvailablePlugins();
}
}
@@ -114,7 +113,8 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
pluginTable.registerKeyboardAction(
new ActionListener() {
- public void actionPerformed(ActionEvent e) {
+ @Override
+ public void actionPerformed(@NotNull ActionEvent e) {
installSelected(pluginTable);
}
},
@@ -235,7 +235,7 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
return new AnAction(availableCategory) {
@Override
public void actionPerformed(AnActionEvent e) {
- final String filter = myFilter.getFilter().toLowerCase();
+ final String filter = myFilter.getFilter().toLowerCase(Locale.ENGLISH);
((AvailablePluginsTableModel)pluginsModel).setCategory(availableCategory, filter);
}
};
@@ -277,7 +277,7 @@ public class AvailablePluginsManagerMain extends PluginManagerMain {
return new AnAction(host) {
@Override
public void actionPerformed(AnActionEvent e) {
- final String filter = myFilter.getFilter().toLowerCase();
+ final String filter = myFilter.getFilter().toLowerCase(Locale.ENGLISH);
((AvailablePluginsTableModel)pluginsModel).setRepository(host, filter);
TableUtil.ensureSelectionExists(getPluginTable());
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
index a1ea238835cd..57329fb8fe9d 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.plugins;
+import com.intellij.diagnostic.PluginException;
import com.intellij.ide.ClassUtilCore;
import com.intellij.ide.IdeBundle;
import com.intellij.idea.IdeaApplication;
@@ -100,31 +101,44 @@ public class PluginManager extends PluginManagerCore {
public static void processException(Throwable t) {
if (!IdeaApplication.isLoaded()) {
- @SuppressWarnings("ThrowableResultOfMethodCallIgnored") StartupAbortedException se = findCause(t);
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") StartupAbortedException se = findCause(t, StartupAbortedException.class);
if (se == null) se = new StartupAbortedException(t);
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") PluginException pe = findCause(t, PluginException.class);
+ PluginId pluginId = pe != null ? pe.getPluginId() : null;
- if (se.logError()) {
+ if (Logger.isInitialized() && !(t instanceof ProcessCanceledException)) {
try {
- if (Logger.isInitialized() && !(t instanceof ProcessCanceledException)) {
- getLogger().error(t);
- }
+ getLogger().error(t);
}
catch (Throwable ignore) { }
+ }
+
+ if (pluginId != null && !CORE_PLUGIN_ID.equals(pluginId.getIdString())) {
+ disablePlugin(pluginId.getIdString());
+
+ StringWriter message = new StringWriter();
+ message.append("Plugin '").append(pluginId.getIdString()).append("' failed to initialize and will be disabled. ");
+ message.append(" Please restart ").append(ApplicationNamesInfo.getInstance().getFullProductName()).append('.');
+ message.append("\n\n");
+ pe.getCause().printStackTrace(new PrintWriter(message));
+ Main.showMessage("Plugin Error", message.toString(), false);
+ System.exit(Main.PLUGIN_ERROR);
+ }
+ else {
Main.showMessage("Start Failed", t);
+ System.exit(se.exitCode());
}
-
- System.exit(se.exitCode());
}
else if (!(t instanceof ProcessCanceledException)) {
getLogger().error(t);
}
}
- private static StartupAbortedException findCause(Throwable t) {
+ private static <T extends Throwable> T findCause(Throwable t, Class<T> clazz) {
while (t != null) {
- if (t instanceof StartupAbortedException) {
- return (StartupAbortedException)t;
+ if (clazz.isInstance(t)) {
+ return clazz.cast(t);
}
t = t.getCause();
}
@@ -229,18 +243,7 @@ public class PluginManager extends PluginManagerCore {
}
if (pluginId != null && !CORE_PLUGIN_ID.equals(pluginId.getIdString())) {
- getLogger().warn(t);
-
- disablePlugin(pluginId.getIdString());
-
- StringWriter message = new StringWriter();
- message.append("Plugin '").append(pluginId.getIdString()).append("' failed to initialize and will be disabled. ");
- message.append(" Please restart ").append(ApplicationNamesInfo.getInstance().getFullProductName()).append('.');
- message.append("\n\n");
- t.printStackTrace(new PrintWriter(message));
- Main.showMessage("Plugin Error", message.toString(), false);
-
- throw new StartupAbortedException(t).exitCode(Main.PLUGIN_ERROR).logError(false);
+ throw new StartupAbortedException(new PluginException(t, pluginId));
}
else {
throw new StartupAbortedException("Fatal error initializing '" + componentClassName + "'", t);
@@ -249,7 +252,6 @@ public class PluginManager extends PluginManagerCore {
private static class StartupAbortedException extends RuntimeException {
private int exitCode = Main.STARTUP_EXCEPTION;
- private boolean logError = true;
public StartupAbortedException(Throwable cause) {
super(cause);
@@ -267,14 +269,5 @@ public class PluginManager extends PluginManagerCore {
this.exitCode = exitCode;
return this;
}
-
- public boolean logError() {
- return logError;
- }
-
- public StartupAbortedException logError(boolean logError) {
- this.logError = logError;
- return this;
- }
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
index 59197a00e70b..550e8e2482e1 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
+++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
@@ -74,7 +74,7 @@
</component>
</children>
</grid>
- <grid id="d9fb" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="d9fb" layout-manager="GridLayoutManager" row-count="1" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -82,17 +82,6 @@
<properties/>
<border type="none"/>
<children>
- <component id="5ea1e" class="javax.swing.JComboBox" binding="myFontSizeCombo" custom-create="true">
- <constraints>
- <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
- <minimum-size width="140" height="-1"/>
- <preferred-size width="140" height="-1"/>
- </grid>
- </constraints>
- <properties>
- <editable value="true"/>
- </properties>
- </component>
<component id="76cd" class="javax.swing.JComboBox" binding="myFontCombo">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
@@ -107,15 +96,6 @@
<requestFocusEnabled value="true"/>
</properties>
</component>
- <component id="4eb1b" class="javax.swing.JLabel" binding="myFontSizeLabel">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <horizontalAlignment value="10"/>
- <text resource-bundle="messages/IdeBundle" key="label.font.size"/>
- </properties>
- </component>
<component id="23221" class="javax.swing.JLabel" binding="myFontNameLabel">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
@@ -127,11 +107,30 @@
</component>
<hspacer id="53ae4">
<constraints>
- <grid row="0" column="0" row-span="2" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
<minimum-size width="20" height="-1"/>
</grid>
</constraints>
</hspacer>
+ <component id="4eb1b" class="javax.swing.JLabel" binding="myFontSizeLabel">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <horizontalAlignment value="10"/>
+ <text resource-bundle="messages/IdeBundle" key="label.font.size"/>
+ </properties>
+ </component>
+ <component id="5ea1e" class="javax.swing.JComboBox" binding="myFontSizeCombo" custom-create="true">
+ <constraints>
+ <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="40" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <editable value="true"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="ce348" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
index bbd52139bd51..7ebf2a57a998 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.util;
+import com.intellij.CommonBundle;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
@@ -97,6 +98,7 @@ public class TipUIUtil {
String minor = ApplicationInfo.getInstance().getMinorVersion();
replaced = replaced.replace("&minorVersion;", minor);
replaced = replaced.replace("&majorMinorVersion;", major + ("0".equals(minor) ? "" : ("." + minor)));
+ replaced = replaced.replace("&settingsPath;", CommonBundle.settingsActionPath());
if (UIUtil.isUnderDarcula()) {
replaced = replaced.replace("css/tips.css", "css/tips_darcula.css");
}
diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
index 94b25a1b3c94..b32729dd7328 100644
--- a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
+++ b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
@@ -24,10 +24,7 @@ import com.intellij.ide.IdeRepaintManager;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.internal.statistic.UsageTrigger;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ApplicationStarter;
-import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
@@ -107,6 +104,12 @@ public class IdeaApplication {
if (myStarter == null) {
myStarter = getStarter();
}
+
+ if (headless && myStarter instanceof ApplicationStarterEx && !((ApplicationStarterEx)myStarter).isHeadless()) {
+ Main.showMessage("Startup Error", "Application cannot start in headless mode", true);
+ System.exit(Main.STARTUP_IMPOSSIBLE);
+ }
+
myStarter.premain(args);
}
@@ -178,10 +181,15 @@ public class IdeaApplication {
catch (ClassNotFoundException ignored) { }
}
- protected class IdeStarter implements ApplicationStarter {
+ protected class IdeStarter extends ApplicationStarterEx {
private Splash mySplash;
@Override
+ public boolean isHeadless() {
+ return false;
+ }
+
+ @Override
public String getCommandName() {
return null;
}
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/actions/ShowDelayedMessageInternalAction.java b/platform/platform-impl/src/com/intellij/notification/impl/actions/ShowDelayedMessageInternalAction.java
new file mode 100644
index 000000000000..ad133f1c7574
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/notification/impl/actions/ShowDelayedMessageInternalAction.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.notification.impl.actions;
+
+import com.intellij.CommonBundle;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationBundle;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.ui.MessageDialogBuilder;
+
+import javax.swing.*;
+
+/**
+ * @author Denis Fokin
+ */
+public class ShowDelayedMessageInternalAction extends AnAction implements DumbAware{
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+
+ new Thread() {
+ @Override
+ public void run() {
+ super.run();
+
+ //noinspection EmptyCatchBlock
+ try {
+ Thread.sleep(3000);
+ }
+ catch (InterruptedException e1) {} // does not matter for an internal action
+
+ //noinspection SSBasedInspection
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ MessageDialogBuilder.yesNo("Nothing happens after that", "Some message goes here").yesText(
+ ApplicationBundle.message("command.exit")).noText(
+ CommonBundle.message("button.cancel")).show();
+ }
+ });
+ }
+ }.start();
+
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
index a17370e73266..bf7c79695c94 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.DecodeDefaultsUtil;
import com.intellij.openapi.components.ExportableApplicationComponent;
import com.intellij.openapi.components.RoamingType;
+import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.BaseSchemeProcessor;
import com.intellij.openapi.options.SchemesManager;
@@ -63,7 +64,7 @@ public class QuickListsManager implements ExportableApplicationComponent, NamedJ
public QuickListsManager(ActionManagerEx actionManagerEx, SchemesManagerFactory schemesManagerFactory) {
myActionManager = actionManagerEx;
mySchemesManager = schemesManagerFactory.createSchemesManager(
- "$ROOT_CONFIG$/quicklists",
+ StoragePathMacros.ROOT_CONFIG + "/quicklists",
new BaseSchemeProcessor<QuickList>(){
public QuickList readScheme(@NotNull final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
return loadListFromDocument(schemeContent);
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
index 723956ef9daa..c5a9b01c4d21 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
@@ -39,6 +39,7 @@ import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.ProjectType;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
@@ -71,28 +72,6 @@ import java.util.*;
import java.util.List;
public final class ActionManagerImpl extends ActionManagerEx implements ApplicationComponent {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionManagerImpl");
- private static final int DEACTIVATED_TIMER_DELAY = 5000;
- private static final int TIMER_DELAY = 500;
- private static final int UPDATE_DELAY_AFTER_TYPING = 500;
-
- private final Object myLock = new Object();
- private final Map<String,Object> myId2Action = new THashMap<String, Object>();
- private final Map<PluginId, THashSet<String>> myPlugin2Id = new THashMap<PluginId, THashSet<String>>();
- private final TObjectIntHashMap<String> myId2Index = new TObjectIntHashMap<String>();
- private final Map<Object,String> myAction2Id = new THashMap<Object, String>();
- private final MultiMap<String,String> myId2GroupId = new MultiMap<String, String>();
- private final List<String> myNotRegisteredInternalActionIds = new ArrayList<String>();
- private MyTimer myTimer;
-
- private int myRegisteredActionsCount;
- private final List<AnActionListener> myActionListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- private String myLastPreformedActionId;
- private final KeymapManager myKeymapManager;
- private final DataManager myDataManager;
- private String myPrevPerformedActionId;
- private long myLastTimeEditorWasTypedIn = 0;
-
@NonNls public static final String ACTION_ELEMENT_NAME = "action";
@NonNls public static final String GROUP_ELEMENT_NAME = "group";
@NonNls public static final String ACTIONS_ELEMENT_NAME = "actions";
@@ -130,14 +109,32 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
@NonNls public static final String USE_SHORTCUT_OF_ATTR_NAME = "use-shortcut-of";
@NonNls public static final String OVERRIDES_ATTR_NAME = "overrides";
@NonNls public static final String KEEP_CONTENT_ATTR_NAME = "keep-content";
-
+ @NonNls public static final String PROJECT_TYPE = "project-type";
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionManagerImpl");
+ private static final int DEACTIVATED_TIMER_DELAY = 5000;
+ private static final int TIMER_DELAY = 500;
+ private static final int UPDATE_DELAY_AFTER_TYPING = 500;
+ private final Object myLock = new Object();
+ private final Map<String,AnAction> myId2Action = new THashMap<String, AnAction>();
+ private final Map<PluginId, THashSet<String>> myPlugin2Id = new THashMap<PluginId, THashSet<String>>();
+ private final TObjectIntHashMap<String> myId2Index = new TObjectIntHashMap<String>();
+ private final Map<Object,String> myAction2Id = new THashMap<Object, String>();
+ private final MultiMap<String,String> myId2GroupId = new MultiMap<String, String>();
+ private final List<String> myNotRegisteredInternalActionIds = new ArrayList<String>();
+ private final List<AnActionListener> myActionListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final KeymapManager myKeymapManager;
+ private final DataManager myDataManager;
private final List<ActionPopupMenuImpl> myPopups = new ArrayList<ActionPopupMenuImpl>();
-
private final Map<AnAction, DataContext> myQueuedNotifications = new LinkedHashMap<AnAction, DataContext>();
private final Map<AnAction, AnActionEvent> myQueuedNotificationsEvents = new LinkedHashMap<AnAction, AnActionEvent>();
-
+ private MyTimer myTimer;
+ private int myRegisteredActionsCount;
+ private String myLastPreformedActionId;
+ private String myPrevPerformedActionId;
+ private long myLastTimeEditorWasTypedIn = 0;
private Runnable myPreloadActionsRunnable;
private boolean myTransparentOnlyUpdate;
+ private int myActionsPreloaded = 0;
ActionManagerImpl(KeymapManager keymapManager, DataManager dataManager) {
myKeymapManager = keymapManager;
@@ -146,6 +143,257 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
registerPluginActions();
}
+ static AnAction convertStub(ActionStub stub) {
+ Object obj;
+ String className = stub.getClassName();
+ try {
+ Class<?> aClass = Class.forName(className, true, stub.getLoader());
+ obj = ReflectionUtil.newInstance(aClass);
+ }
+ catch (ClassNotFoundException e) {
+ PluginId pluginId = stub.getPluginId();
+ if (pluginId != null) {
+ throw new PluginException("class with name \"" + className + "\" not found", e, pluginId);
+ }
+ else {
+ throw new IllegalStateException("class with name \"" + className + "\" not found");
+ }
+ }
+ catch(UnsupportedClassVersionError e) {
+ PluginId pluginId = stub.getPluginId();
+ if (pluginId != null) {
+ throw new PluginException(e, pluginId);
+ }
+ else {
+ throw new IllegalStateException(e);
+ }
+ }
+ catch (Exception e) {
+ PluginId pluginId = stub.getPluginId();
+ if (pluginId != null) {
+ throw new PluginException("cannot create class \"" + className + "\"", e, pluginId);
+ }
+ else {
+ throw new IllegalStateException("cannot create class \"" + className + "\"", e);
+ }
+ }
+
+ if (!(obj instanceof AnAction)) {
+ throw new IllegalStateException("class with name '" + className + "' must be an instance of '" + AnAction.class.getName()+"'; got "+obj);
+ }
+
+ AnAction anAction = (AnAction)obj;
+ stub.initAction(anAction);
+ if (StringUtil.isNotEmpty(stub.getText())) {
+ anAction.getTemplatePresentation().setText(stub.getText());
+ }
+ String iconPath = stub.getIconPath();
+ if (iconPath != null) {
+ Class<? extends AnAction> actionClass = anAction.getClass();
+ setIconFromClass(actionClass, actionClass.getClassLoader(), iconPath, anAction.getTemplatePresentation(), stub.getPluginId());
+ }
+ return anAction;
+ }
+
+ private static void processAbbreviationNode(Element e, String id) {
+ final String abbr = e.getAttributeValue(VALUE_ATTR_NAME);
+ if (!StringUtil.isEmpty(abbr)) {
+ final AbbreviationManagerImpl abbreviationManager = ((AbbreviationManagerImpl)AbbreviationManager.getInstance());
+ abbreviationManager.register(abbr, id, true);
+ }
+ }
+
+ @Nullable
+ private static ResourceBundle getActionsResourceBundle(ClassLoader loader, IdeaPluginDescriptor plugin) {
+ @NonNls final String resBundleName = plugin != null && !"com.intellij".equals(plugin.getPluginId().getIdString())
+ ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE;
+ ResourceBundle bundle = null;
+ if (resBundleName != null) {
+ bundle = AbstractBundle.getResourceBundle(resBundleName, loader);
+ }
+ return bundle;
+ }
+
+ private static boolean isSecondary(Element element) {
+ return "true".equalsIgnoreCase(element.getAttributeValue(SECONDARY));
+ }
+
+ private static void setIcon(@Nullable final String iconPath,
+ @NotNull String className,
+ @NotNull ClassLoader loader,
+ @NotNull Presentation presentation,
+ final PluginId pluginId) {
+ if (iconPath == null) return;
+
+ try {
+ final Class actionClass = Class.forName(className, true, loader);
+ setIconFromClass(actionClass, loader, iconPath, presentation, pluginId);
+ }
+ catch (ClassNotFoundException e) {
+ LOG.error(e);
+ reportActionError(pluginId, "class with name \"" + className + "\" not found");
+ }
+ catch (NoClassDefFoundError e) {
+ LOG.error(e);
+ reportActionError(pluginId, "class with name \"" + className + "\" not found");
+ }
+ }
+
+ private static void setIconFromClass(@NotNull final Class actionClass,
+ @NotNull final ClassLoader classLoader,
+ @NotNull final String iconPath,
+ @NotNull Presentation presentation,
+ final PluginId pluginId) {
+ final IconLoader.LazyIcon lazyIcon = new IconLoader.LazyIcon() {
+ @Override
+ protected Icon compute() {
+ //try to find icon in idea class path
+ Icon icon = IconLoader.findIcon(iconPath, actionClass, true);
+ if (icon == null) {
+ icon = IconLoader.findIcon(iconPath, classLoader);
+ }
+
+ if (icon == null) {
+ reportActionError(pluginId, "Icon cannot be found in '" + iconPath + "', action '" + actionClass + "'");
+ }
+
+ return icon;
+ }
+
+ @Override
+ public String toString() {
+ return "LazyIcon@ActionManagerImpl (path: " + iconPath + ", action class: " + actionClass + ")";
+ }
+ };
+
+ if (!Registry.is("ide.lazyIconLoading")) {
+ lazyIcon.load();
+ }
+
+ presentation.setIcon(lazyIcon);
+ }
+
+ private static String loadDescriptionForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) {
+ final String value = element.getAttributeValue(DESCRIPTION);
+ if (bundle != null) {
+ @NonNls final String key = elementType + "." + id + ".description";
+ return CommonBundle.messageOrDefault(bundle, key, value == null ? "" : value);
+ } else {
+ return value;
+ }
+ }
+
+ private static String loadTextForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) {
+ final String value = element.getAttributeValue(TEXT_ATTR_NAME);
+ return CommonBundle.messageOrDefault(bundle, elementType + "." + id + "." + TEXT_ATTR_NAME, value == null ? "" : value);
+ }
+
+ public static boolean checkRelativeToAction(final String relativeToActionId,
+ @NotNull final Anchor anchor,
+ @NotNull final String actionName,
+ @Nullable final PluginId pluginId) {
+ if ((Anchor.BEFORE == anchor || Anchor.AFTER == anchor) && relativeToActionId == null) {
+ reportActionError(pluginId, actionName + ": \"relative-to-action\" cannot be null if anchor is \"after\" or \"before\"");
+ return false;
+ }
+ return true;
+ }
+
+ @Nullable
+ public static Anchor parseAnchor(final String anchorStr,
+ @Nullable final String actionName,
+ @Nullable final PluginId pluginId) {
+ if (anchorStr == null) {
+ return Anchor.LAST;
+ }
+
+ if (FIRST.equalsIgnoreCase(anchorStr)) {
+ return Anchor.FIRST;
+ }
+ else if (LAST.equalsIgnoreCase(anchorStr)) {
+ return Anchor.LAST;
+ }
+ else if (BEFORE.equalsIgnoreCase(anchorStr)) {
+ return Anchor.BEFORE;
+ }
+ else if (AFTER.equalsIgnoreCase(anchorStr)) {
+ return Anchor.AFTER;
+ }
+ else {
+ reportActionError(pluginId, actionName + ": anchor should be one of the following constants: \"first\", \"last\", \"before\" or \"after\"");
+ return null;
+ }
+ }
+
+ private static void processMouseShortcutNode(Element element, String actionId, PluginId pluginId) {
+ String keystrokeString = element.getAttributeValue(KEYSTROKE_ATTR_NAME);
+ if (keystrokeString == null || keystrokeString.trim().isEmpty()) {
+ reportActionError(pluginId, "\"keystroke\" attribute must be specified for action with id=" + actionId);
+ return;
+ }
+ MouseShortcut shortcut;
+ try {
+ shortcut = KeymapUtil.parseMouseShortcut(keystrokeString);
+ }
+ catch (Exception ex) {
+ reportActionError(pluginId, "\"keystroke\" attribute has invalid value for action with id=" + actionId);
+ return;
+ }
+
+ String keymapName = element.getAttributeValue(KEYMAP_ATTR_NAME);
+ if (keymapName == null || keymapName.isEmpty()) {
+ reportActionError(pluginId, "attribute \"keymap\" should be defined");
+ return;
+ }
+ Keymap keymap = KeymapManager.getInstance().getKeymap(keymapName);
+ if (keymap == null) {
+ reportActionError(pluginId, "keymap \"" + keymapName + "\" not found");
+ return;
+ }
+
+ final String removeOption = element.getAttributeValue(REMOVE_SHORTCUT_ATTR_NAME);
+ if (Boolean.valueOf(removeOption)) {
+ keymap.removeShortcut(actionId, shortcut);
+ } else {
+ keymap.addShortcut(actionId, shortcut);
+ }
+ }
+
+ private static void assertActionIsGroupOrStub(final AnAction action) {
+ if (!(action instanceof ActionGroup || action instanceof ActionStub)) {
+ LOG.error("Action : " + action + "; class: " + action.getClass());
+ }
+ }
+
+ private static void reportActionError(final PluginId pluginId, @NonNls @NotNull String message) {
+ if (pluginId == null) {
+ LOG.error(message);
+ }
+ else {
+ LOG.error(new PluginException(message, null, pluginId));
+ }
+ }
+
+ @NonNls
+ private static String getPluginInfo(@Nullable PluginId id) {
+ if (id != null) {
+ final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id);
+ if (plugin != null) {
+ String name = plugin.getName();
+ if (name == null) {
+ name = id.getIdString();
+ }
+ return " Plugin: " + name;
+ }
+ }
+ return "";
+ }
+
+ private static DataContext getContextBy(Component contextComponent) {
+ final DataManager dataManager = DataManager.getInstance();
+ return contextComponent != null ? dataManager.getDataContext(contextComponent) : dataManager.getDataContext();
+ }
+
@Override
public void initComponent() {}
@@ -213,7 +461,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return new ActionToolbarImpl(place, group, horizontal, decorateButtons, myDataManager, this, (KeymapManagerEx)myKeymapManager);
}
-
private void registerPluginActions() {
final IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins();
for (IdeaPluginDescriptor plugin : plugins) {
@@ -229,12 +476,28 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
@Override
public AnAction getAction(@NotNull String id) {
- return getActionImpl(id, false);
+ return getActionImpl(id, false, null);
}
- private AnAction getActionImpl(String id, boolean canReturnStub) {
+ @Override
+ public AnAction getAction(@NonNls @NotNull String actionId, @Nullable ProjectType projectType) {
+ return getActionImpl(actionId, false, projectType);
+ }
+
+ private AnAction getActionImpl(String id, boolean canReturnStub, ProjectType projectType) {
synchronized (myLock) {
- AnAction action = (AnAction)myId2Action.get(id);
+ AnAction action;
+ Object o = myId2Action.get(id);
+ if (o == null) {
+ return null;
+ }
+ if (o instanceof AnAction) {
+ action = (AnAction)o;
+ }
+ else {
+ //noinspection unchecked
+ action = ((Map<ProjectType, AnAction>)o).get(projectType);
+ }
if (!canReturnStub && action instanceof ActionStub) {
action = convert((ActionStub)action);
}
@@ -252,61 +515,14 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
LOG.assertTrue(myId2Action.containsKey(stub.getId()));
- AnAction action = (AnAction)myId2Action.remove(stub.getId());
+ AnAction action = myId2Action.remove(stub.getId());
LOG.assertTrue(action != null);
LOG.assertTrue(action.equals(stub));
- Object obj;
- String className = stub.getClassName();
- try {
- Class<?> aClass = Class.forName(className, true, stub.getLoader());
- obj = ReflectionUtil.newInstance(aClass);
- }
- catch (ClassNotFoundException e) {
- PluginId pluginId = stub.getPluginId();
- if (pluginId != null) {
- throw new PluginException("class with name \"" + className + "\" not found", e, pluginId);
- }
- else {
- throw new IllegalStateException("class with name \"" + className + "\" not found");
- }
- }
- catch(UnsupportedClassVersionError e) {
- PluginId pluginId = stub.getPluginId();
- if (pluginId != null) {
- throw new PluginException(e, pluginId);
- }
- else {
- throw new IllegalStateException(e);
- }
- }
- catch (Exception e) {
- PluginId pluginId = stub.getPluginId();
- if (pluginId != null) {
- throw new PluginException("cannot create class \"" + className + "\"", e, pluginId);
- }
- else {
- throw new IllegalStateException("cannot create class \"" + className + "\"", e);
- }
- }
-
- if (!(obj instanceof AnAction)) {
- throw new IllegalStateException("class with name '" + className + "' must be an instance of '" + AnAction.class.getName()+"'; got "+obj);
- }
+ AnAction anAction = convertStub(stub);
- AnAction anAction = (AnAction)obj;
- stub.initAction(anAction);
- if (StringUtil.isNotEmpty(stub.getText())) {
- anAction.getTemplatePresentation().setText(stub.getText());
- }
- String iconPath = stub.getIconPath();
- if (iconPath != null) {
- Class<? extends AnAction> actionClass = anAction.getClass();
- setIconFromClass(actionClass, actionClass.getClassLoader(), iconPath, anAction.getTemplatePresentation(), stub.getPluginId());
- }
-
- myId2Action.put(stub.getId(), obj);
- myAction2Id.put(obj, stub.getId());
+ addToMap(stub.getId(), anAction, stub.getPluginId(), stub.getProjectType() == null ? null : new ProjectType(stub.getProjectType()));
+ myAction2Id.put(anAction, stub.getId());
return anAction;
}
@@ -334,7 +550,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
@Override
public boolean isGroup(@NotNull String actionId) {
- return getActionImpl(actionId, true) instanceof ActionGroup;
+ return getActionImpl(actionId, true, null) instanceof ActionGroup;
}
@Override
@@ -344,7 +560,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
@Override
public AnAction getActionOrStub(String id) {
- return getActionImpl(id, true);
+ return getActionImpl(id, true, null);
}
/**
@@ -386,7 +602,8 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return null;
}
- ActionStub stub = new ActionStub(className, id, text, loader, pluginId, iconPath);
+ String projectType = element.getAttributeValue(PROJECT_TYPE);
+ ActionStub stub = new ActionStub(className, id, text, loader, pluginId, iconPath, projectType);
Presentation presentation = stub.getTemplatePresentation();
presentation.setText(text);
@@ -441,99 +658,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- private static void processAbbreviationNode(Element e, String id) {
- final String abbr = e.getAttributeValue(VALUE_ATTR_NAME);
- if (!StringUtil.isEmpty(abbr)) {
- final AbbreviationManagerImpl abbreviationManager = ((AbbreviationManagerImpl)AbbreviationManager.getInstance());
- abbreviationManager.register(abbr, id, true);
- }
- }
-
- @Nullable
- private static ResourceBundle getActionsResourceBundle(ClassLoader loader, IdeaPluginDescriptor plugin) {
- @NonNls final String resBundleName = plugin != null && !"com.intellij".equals(plugin.getPluginId().getIdString())
- ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE;
- ResourceBundle bundle = null;
- if (resBundleName != null) {
- bundle = AbstractBundle.getResourceBundle(resBundleName, loader);
- }
- return bundle;
- }
-
- private static boolean isSecondary(Element element) {
- return "true".equalsIgnoreCase(element.getAttributeValue(SECONDARY));
- }
-
- private static void setIcon(@Nullable final String iconPath,
- @NotNull String className,
- @NotNull ClassLoader loader,
- @NotNull Presentation presentation,
- final PluginId pluginId) {
- if (iconPath == null) return;
-
- try {
- final Class actionClass = Class.forName(className, true, loader);
- setIconFromClass(actionClass, loader, iconPath, presentation, pluginId);
- }
- catch (ClassNotFoundException e) {
- LOG.error(e);
- reportActionError(pluginId, "class with name \"" + className + "\" not found");
- }
- catch (NoClassDefFoundError e) {
- LOG.error(e);
- reportActionError(pluginId, "class with name \"" + className + "\" not found");
- }
- }
-
- private static void setIconFromClass(@NotNull final Class actionClass,
- @NotNull final ClassLoader classLoader,
- @NotNull final String iconPath,
- @NotNull Presentation presentation,
- final PluginId pluginId) {
- final IconLoader.LazyIcon lazyIcon = new IconLoader.LazyIcon() {
- @Override
- protected Icon compute() {
- //try to find icon in idea class path
- Icon icon = IconLoader.findIcon(iconPath, actionClass, true);
- if (icon == null) {
- icon = IconLoader.findIcon(iconPath, classLoader);
- }
-
- if (icon == null) {
- reportActionError(pluginId, "Icon cannot be found in '" + iconPath + "', action '" + actionClass + "'");
- }
-
- return icon;
- }
-
- @Override
- public String toString() {
- return "LazyIcon@ActionManagerImpl (path: " + iconPath + ", action class: " + actionClass + ")";
- }
- };
-
- if (!Registry.is("ide.lazyIconLoading")) {
- lazyIcon.load();
- }
-
- presentation.setIcon(lazyIcon);
- }
-
- private static String loadDescriptionForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) {
- final String value = element.getAttributeValue(DESCRIPTION);
- if (bundle != null) {
- @NonNls final String key = elementType + "." + id + ".description";
- return CommonBundle.messageOrDefault(bundle, key, value == null ? "" : value);
- } else {
- return value;
- }
- }
-
- private static String loadTextForElement(final Element element, final ResourceBundle bundle, final String id, String elementType) {
- final String value = element.getAttributeValue(TEXT_ATTR_NAME);
- return CommonBundle.messageOrDefault(bundle, elementType + "." + id + "." + TEXT_ATTR_NAME, value == null ? "" : value);
- }
-
private AnAction processGroupElement(Element element, final ClassLoader loader, PluginId pluginId) {
final IdeaPluginDescriptor plugin = PluginManager.getPlugin(pluginId);
ResourceBundle bundle = getActionsResourceBundle(loader, plugin);
@@ -723,43 +847,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
myId2GroupId.putValue(myAction2Id.get(action), myAction2Id.get(group));
}
- public static boolean checkRelativeToAction(final String relativeToActionId,
- @NotNull final Anchor anchor,
- @NotNull final String actionName,
- @Nullable final PluginId pluginId) {
- if ((Anchor.BEFORE == anchor || Anchor.AFTER == anchor) && relativeToActionId == null) {
- reportActionError(pluginId, actionName + ": \"relative-to-action\" cannot be null if anchor is \"after\" or \"before\"");
- return false;
- }
- return true;
- }
-
- @Nullable
- public static Anchor parseAnchor(final String anchorStr,
- @Nullable final String actionName,
- @Nullable final PluginId pluginId) {
- if (anchorStr == null) {
- return Anchor.LAST;
- }
-
- if (FIRST.equalsIgnoreCase(anchorStr)) {
- return Anchor.FIRST;
- }
- else if (LAST.equalsIgnoreCase(anchorStr)) {
- return Anchor.LAST;
- }
- else if (BEFORE.equalsIgnoreCase(anchorStr)) {
- return Anchor.BEFORE;
- }
- else if (AFTER.equalsIgnoreCase(anchorStr)) {
- return Anchor.AFTER;
- }
- else {
- reportActionError(pluginId, actionName + ": anchor should be one of the following constants: \"first\", \"last\", \"before\" or \"after\"");
- return null;
- }
- }
-
@Nullable
public AnAction getParentGroup(final String groupId,
@Nullable final String actionName,
@@ -768,10 +855,10 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
reportActionError(pluginId, actionName + ": attribute \"group-id\" should be defined");
return null;
}
- AnAction parentGroup = getActionImpl(groupId, true);
+ AnAction parentGroup = getActionImpl(groupId, true, null);
if (parentGroup == null) {
reportActionError(pluginId, actionName + ": group with id \"" + groupId + "\" isn't registered; action will be added to the \"Other\" group");
- parentGroup = getActionImpl(IdeActions.GROUP_OTHER_MENU, true);
+ parentGroup = getActionImpl(IdeActions.GROUP_OTHER_MENU, true, null);
}
if (!(parentGroup instanceof DefaultActionGroup)) {
reportActionError(pluginId, actionName + ": group with id \"" + groupId + "\" should be instance of " + DefaultActionGroup.class.getName() +
@@ -850,40 +937,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- private static void processMouseShortcutNode(Element element, String actionId, PluginId pluginId) {
- String keystrokeString = element.getAttributeValue(KEYSTROKE_ATTR_NAME);
- if (keystrokeString == null || keystrokeString.trim().isEmpty()) {
- reportActionError(pluginId, "\"keystroke\" attribute must be specified for action with id=" + actionId);
- return;
- }
- MouseShortcut shortcut;
- try {
- shortcut = KeymapUtil.parseMouseShortcut(keystrokeString);
- }
- catch (Exception ex) {
- reportActionError(pluginId, "\"keystroke\" attribute has invalid value for action with id=" + actionId);
- return;
- }
-
- String keymapName = element.getAttributeValue(KEYMAP_ATTR_NAME);
- if (keymapName == null || keymapName.isEmpty()) {
- reportActionError(pluginId, "attribute \"keymap\" should be defined");
- return;
- }
- Keymap keymap = KeymapManager.getInstance().getKeymap(keymapName);
- if (keymap == null) {
- reportActionError(pluginId, "keymap \"" + keymapName + "\" not found");
- return;
- }
-
- final String removeOption = element.getAttributeValue(REMOVE_SHORTCUT_ATTR_NAME);
- if (Boolean.valueOf(removeOption)) {
- keymap.removeShortcut(actionId, shortcut);
- } else {
- keymap.addShortcut(actionId, shortcut);
- }
- }
-
@Nullable
private AnAction processReferenceElement(Element element, PluginId pluginId) {
if (!REFERENCE_ELEMENT_NAME.equals(element.getName())) {
@@ -902,7 +955,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return null;
}
- AnAction action = getActionImpl(ref, true);
+ AnAction action = getActionImpl(ref, true, null);
if (action == null) {
if (!myNotRegisteredInternalActionIds.contains(ref)) {
@@ -936,27 +989,15 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- private static void assertActionIsGroupOrStub(final AnAction action) {
- if (!(action instanceof ActionGroup || action instanceof ActionStub)) {
- LOG.error("Action : " + action + "; class: " + action.getClass());
- }
- }
-
@Override
public void registerAction(@NotNull String actionId, @NotNull AnAction action, @Nullable PluginId pluginId) {
synchronized (myLock) {
- if (myId2Action.containsKey(actionId)) {
- reportActionError(pluginId, "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action +
- "; Registered action is " +
- myId2Action.get(actionId) + getPluginInfo(pluginId));
- return;
- }
+ if (!addToMap(actionId, action, pluginId, null)) return;
if (myAction2Id.containsKey(action)) {
reportActionError(pluginId, "action was already registered for another ID. ID is " + myAction2Id.get(action) +
getPluginInfo(pluginId));
return;
}
- myId2Action.put(actionId, action);
myId2Index.put(actionId, myRegisteredActionsCount++);
myAction2Id.put(action, actionId);
if (pluginId != null && !(action instanceof ActionGroup)){
@@ -971,28 +1012,31 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- private static void reportActionError(final PluginId pluginId, @NonNls @NotNull String message) {
- if (pluginId == null) {
- LOG.error(message);
+ public boolean addToMap(String actionId, AnAction action, PluginId pluginId, ProjectType projectType) {
+ if (myId2Action.containsKey(actionId)) {
+ // make sure id+projectType is unique
+ AnAction o = myId2Action.get(actionId);
+ ChameleonAction chameleonAction;
+ if (o instanceof ChameleonAction) {
+ chameleonAction = (ChameleonAction)o;
+ }
+ else {
+ chameleonAction = new ChameleonAction(o, projectType);
+ myId2Action.put(actionId, chameleonAction);
+ }
+ AnAction old = chameleonAction.addAction(action, projectType);
+ if (old != null) {
+ reportActionError(pluginId,
+ "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action +
+ "; Registered action is " +
+ myId2Action.get(actionId) + getPluginInfo(pluginId));
+ return false;
+ }
}
else {
- LOG.error(new PluginException(message, null, pluginId));
- }
- }
-
- @NonNls
- private static String getPluginInfo(@Nullable PluginId id) {
- if (id != null) {
- final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id);
- if (plugin != null) {
- String name = plugin.getName();
- if (name == null) {
- name = id.getIdString();
- }
- return " Plugin: " + name;
- }
+ myId2Action.put(actionId, action);
}
- return "";
+ return true;
}
@Override
@@ -1067,6 +1111,12 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
+ //@Override
+ //public AnAction replaceAction(String actionId, @NotNull AnAction newAction) {
+ // synchronized (myLock) {
+ // return replaceAction(actionId, newAction, null);
+ // }
+ //}
@Override
public boolean isActionPopupStackEmpty() {
@@ -1078,13 +1128,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return myTransparentOnlyUpdate;
}
- //@Override
- //public AnAction replaceAction(String actionId, @NotNull AnAction newAction) {
- // synchronized (myLock) {
- // return replaceAction(actionId, newAction, null);
- // }
- //}
-
private AnAction replaceAction(@NotNull String actionId, @NotNull AnAction newAction, @Nullable PluginId pluginId) {
AnAction oldAction = getActionOrStub(actionId);
if (oldAction != null) {
@@ -1208,8 +1251,6 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- private int myActionsPreloaded = 0;
-
public void preloadActions() {
if (myPreloadActionsRunnable == null) {
myPreloadActionsRunnable = new Runnable() {
@@ -1281,6 +1322,85 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
+ @Override
+ public ActionCallback tryToExecute(@NotNull final AnAction action, @NotNull final InputEvent inputEvent, @Nullable final Component contextComponent, @Nullable final String place,
+ boolean now) {
+
+ final Application app = ApplicationManager.getApplication();
+ assert app.isDispatchThread();
+
+ final ActionCallback result = new ActionCallback();
+ final Runnable doRunnable = new Runnable() {
+ @Override
+ public void run() {
+ tryToExecuteNow(action, inputEvent, contextComponent, place, result);
+ }
+ };
+
+ if (now) {
+ doRunnable.run();
+ } else {
+ //noinspection SSBasedInspection
+ SwingUtilities.invokeLater(doRunnable);
+ }
+
+ return result;
+ }
+
+ private void tryToExecuteNow(final AnAction action, final InputEvent inputEvent, final Component contextComponent, final String place, final ActionCallback result) {
+ final Presentation presentation = action.getTemplatePresentation().clone();
+
+ IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown(new Runnable() {
+ @Override
+ public void run() {
+ final DataContext context = getContextBy(contextComponent);
+
+ AnActionEvent event = new AnActionEvent(
+ inputEvent, context,
+ place != null ? place : ActionPlaces.UNKNOWN,
+ presentation, ActionManagerImpl.this,
+ inputEvent.getModifiersEx()
+ );
+
+ ActionUtil.performDumbAwareUpdate(action, event, false);
+ if (!event.getPresentation().isEnabled()) {
+ result.setRejected();
+ return;
+ }
+
+ ActionUtil.lastUpdateAndCheckDumb(action, event, false);
+ if (!event.getPresentation().isEnabled()) {
+ result.setRejected();
+ return;
+ }
+
+ Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(context);
+ if (component != null && !component.isShowing()) {
+ result.setRejected();
+ return;
+ }
+
+ fireBeforeActionPerformed(action, context, event);
+
+ UIUtil.addAwtListener(new AWTEventListener() {
+ @Override
+ public void eventDispatched(AWTEvent event) {
+ if (event.getID() == WindowEvent.WINDOW_OPENED ||event.getID() == WindowEvent.WINDOW_ACTIVATED) {
+ if (!result.isProcessed()) {
+ final WindowEvent we = (WindowEvent)event;
+ IdeFocusManager.findInstanceByComponent(we.getWindow()).doWhenFocusSettlesDown(result.createSetDoneRunnable());
+ }
+ }
+ }
+ }, AWTEvent.WINDOW_EVENT_MASK, result);
+
+ ActionUtil.performActionDumbAware(action, event);
+ result.setDone();
+ queueActionPerformedEvent(action, context, event);
+ }
+ });
+ }
+
private class MyTimer extends Timer implements ActionListener {
private final List<TimerListener> myTimerListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final List<TimerListener> myTransparentTimerListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@@ -1371,88 +1491,4 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
}
-
- @Override
- public ActionCallback tryToExecute(@NotNull final AnAction action, @NotNull final InputEvent inputEvent, @Nullable final Component contextComponent, @Nullable final String place,
- boolean now) {
-
- final Application app = ApplicationManager.getApplication();
- assert app.isDispatchThread();
-
- final ActionCallback result = new ActionCallback();
- final Runnable doRunnable = new Runnable() {
- @Override
- public void run() {
- tryToExecuteNow(action, inputEvent, contextComponent, place, result);
- }
- };
-
- if (now) {
- doRunnable.run();
- } else {
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(doRunnable);
- }
-
- return result;
- }
-
- private void tryToExecuteNow(final AnAction action, final InputEvent inputEvent, final Component contextComponent, final String place, final ActionCallback result) {
- final Presentation presentation = action.getTemplatePresentation().clone();
-
- IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown(new Runnable() {
- @Override
- public void run() {
- final DataContext context = getContextBy(contextComponent);
-
- AnActionEvent event = new AnActionEvent(
- inputEvent, context,
- place != null ? place : ActionPlaces.UNKNOWN,
- presentation, ActionManagerImpl.this,
- inputEvent.getModifiersEx()
- );
-
- ActionUtil.performDumbAwareUpdate(action, event, false);
- if (!event.getPresentation().isEnabled()) {
- result.setRejected();
- return;
- }
-
- ActionUtil.lastUpdateAndCheckDumb(action, event, false);
- if (!event.getPresentation().isEnabled()) {
- result.setRejected();
- return;
- }
-
- Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(context);
- if (component != null && !component.isShowing()) {
- result.setRejected();
- return;
- }
-
- fireBeforeActionPerformed(action, context, event);
-
- UIUtil.addAwtListener(new AWTEventListener() {
- @Override
- public void eventDispatched(AWTEvent event) {
- if (event.getID() == WindowEvent.WINDOW_OPENED ||event.getID() == WindowEvent.WINDOW_ACTIVATED) {
- if (!result.isProcessed()) {
- final WindowEvent we = (WindowEvent)event;
- IdeFocusManager.findInstanceByComponent(we.getWindow()).doWhenFocusSettlesDown(result.createSetDoneRunnable());
- }
- }
- }
- }, AWTEvent.WINDOW_EVENT_MASK, result);
-
- ActionUtil.performActionDumbAware(action, event);
- result.setDone();
- queueActionPerformedEvent(action, context, event);
- }
- });
- }
-
- private static DataContext getContextBy(Component contextComponent) {
- final DataManager dataManager = DataManager.getInstance();
- return contextComponent != null ? dataManager.getDataContext(contextComponent) : dataManager.getDataContext();
- }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java
new file mode 100644
index 000000000000..4b46dc191c0c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.actionSystem.impl;
+
+import com.intellij.openapi.actionSystem.ActionStub;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectType;
+import com.intellij.openapi.project.ProjectTypeService;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class ChameleonAction extends AnAction {
+
+ private final Map<ProjectType, AnAction> myActions = new HashMap<ProjectType, AnAction>();
+
+ public ChameleonAction(@NotNull AnAction first, ProjectType projectType) {
+ addAction(first, projectType);
+ }
+
+ public AnAction addAction(AnAction action, ProjectType projectType) {
+ if (action instanceof ActionStub) {
+ String type = ((ActionStub)action).getProjectType();
+ action = ActionManagerImpl.convertStub((ActionStub)action);
+ projectType = type == null ? null : new ProjectType(type);
+ }
+ return myActions.put(projectType, action);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ getAction(e).actionPerformed(e);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ }
+
+ private AnAction getAction(AnActionEvent e) {
+ Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
+ ProjectType projectType = ProjectTypeService.getProjectType(project);
+ AnAction action = myActions.get(projectType);
+ if (action == null) action = myActions.get(null);
+ if (action == null) action = myActions.values().iterator().next();
+ return action;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
index 01aa0ff4c49e..4de847213103 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
@@ -40,7 +40,6 @@ public class ActionBean {
@Attribute(ActionManagerImpl.ICON_ATTR_NAME)
public String icon;
-
@Attribute(ActionManagerImpl.POPUP_ATTR_NAME)
public String isPopup;
@@ -58,4 +57,7 @@ public class ActionBean {
@Attribute(ActionManagerImpl.OVERRIDES_ATTR_NAME)
public boolean overrides;
+
+ @Attribute(ActionManagerImpl.PROJECT_TYPE)
+ public String projectType;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index 46fae517170d..e3a36a2e59ab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
@@ -336,25 +336,26 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
}
private boolean disposeSelf(final boolean checkCanCloseProject) {
- final CommandProcessor commandProcessor = CommandProcessor.getInstance();
- final boolean[] canClose = {true};
- for (final Project project : ProjectManagerEx.getInstanceEx().getOpenProjects()) {
- try {
- commandProcessor.executeCommand(project, new Runnable() {
- @Override
- public void run() {
- final ProjectManagerImpl manager = (ProjectManagerImpl)ProjectManagerEx.getInstanceEx();
- if (!manager.closeProject(project, true, true, checkCanCloseProject)) {
- canClose[0] = false;
+ final ProjectManagerImpl manager = (ProjectManagerImpl)ProjectManagerEx.getInstanceEx();
+ if (manager != null) {
+ final boolean[] canClose = {true};
+ for (final Project project : manager.getOpenProjects()) {
+ try {
+ CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ @Override
+ public void run() {
+ if (!manager.closeProject(project, true, true, checkCanCloseProject)) {
+ canClose[0] = false;
+ }
}
- }
- }, ApplicationBundle.message("command.exit"), null);
- }
- catch (Throwable e) {
- LOG.error(e);
- }
- if (!canClose[0]) {
- return false;
+ }, ApplicationBundle.message("command.exit"), null);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ if (!canClose[0]) {
+ return false;
+ }
}
}
runWriteAction(new Runnable() {
@@ -529,9 +530,13 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
}
@Override
- public void load(String path) throws IOException, InvalidDataException {
- getStateStore().setOptionsPath(path);
- getStateStore().setConfigPath(PathManager.getConfigPath());
+ public void load(@Nullable String optionsPath) throws IOException {
+ load(PathManager.getConfigPath(), optionsPath);
+ }
+
+ public void load(@NotNull String configPath, @Nullable String optionsPath) throws IOException {
+ getStateStore().setOptionsPath(optionsPath);
+ getStateStore().setConfigPath(configPath);
myIsFiringLoadingEvent = true;
try {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
index 41942960ab04..a00533d3244b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.util.NamedJDOMExternalizable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Collection;
@@ -36,13 +37,14 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
private static final String XML_EXTENSION = ".xml";
private static final String DEFAULT_STORAGE_SPEC = StoragePathMacros.APP_CONFIG + "/" + PathManager.DEFAULT_OPTIONS_FILE_NAME + XML_EXTENSION;
private static final String OPTIONS_MACRO = "OPTIONS";
- private static final String CONFIG_MACRO = "ROOT_CONFIG";
private static final String ROOT_ELEMENT_NAME = "application";
private final ApplicationImpl myApplication;
private final StateStorageManager myStateStorageManager;
private final DefaultsStateStorage myDefaultsStateStorage;
+ private String myConfigPath;
+
// created from PicoContainer
@SuppressWarnings({"UnusedDeclaration"})
public ApplicationStoreImpl(final ApplicationImpl application, PathMacroManager pathMacroManager) {
@@ -53,23 +55,24 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
return new FileBasedStorage.FileStorageData(ROOT_ELEMENT_NAME);
}
+ @Nullable
@Override
protected String getOldStorageSpec(Object component, final String componentName, final StateStorageOperation operation) {
- final String fileName;
-
if (component instanceof NamedJDOMExternalizable) {
- fileName = StoragePathMacros.APP_CONFIG + "/" + ((NamedJDOMExternalizable)component).getExternalFileName() + XML_EXTENSION;
+ return StoragePathMacros.APP_CONFIG + "/" + ((NamedJDOMExternalizable)component).getExternalFileName() + XML_EXTENSION;
}
else {
- fileName = DEFAULT_STORAGE_SPEC;
+ return DEFAULT_STORAGE_SPEC;
}
-
- return fileName;
}
@Override
protected String getVersionsFilePath() {
- return PathManager.getConfigPath() + "/options/appComponentVersions.xml";
+ String configPath = myConfigPath;
+ if (configPath == null) {
+ configPath = PathManager.getConfigPath();
+ }
+ return configPath + "/options/appComponentVersions.xml";
}
@Override
@@ -97,7 +100,8 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
@Override
public void setConfigPath(@NotNull final String configPath) {
- myStateStorageManager.addMacro(CONFIG_MACRO, configPath);
+ myStateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.ROOT_CONFIG), configPath);
+ myConfigPath = configPath;
}
@Override
@@ -150,6 +154,7 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
return myStateStorageManager;
}
+ @Nullable
@Override
protected StateStorage getDefaultsStorage() {
return myDefaultsStateStorage;
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
index 01cc0fb987b9..25dd8a05cab3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.components.impl.stores;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.impl.ProjectManagerImpl;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -28,8 +27,6 @@ import java.util.ArrayList;
import java.util.Set;
abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.BaseFileConfigurableStoreImpl");
-
@NonNls protected static final String VERSION_OPTION = "version";
@NonNls public static final String ATTRIBUTE_NAME = "name";
private final ComponentManager myComponentManager;
@@ -119,6 +116,7 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
return (BaseStorageData) getMainStorage().getStorageData(false);
}
+ @Nullable
@Override
protected StateStorage getDefaultsStorage() {
return myDefaultsStateStorage;
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
index 575717f455f7..fc2017b57a4a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
@@ -41,8 +41,7 @@ import java.util.*;
@SuppressWarnings({"deprecation"})
public abstract class ComponentStoreImpl implements IComponentStore {
-
- private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentStoreImpl");
+ private static final Logger LOG = Logger.getInstance(ComponentStoreImpl.class);
private final Map<String, Object> myComponents = Collections.synchronizedMap(new THashMap<String, Object>());
private final List<SettingsSavingComponent> mySettingsSavingComponents = Collections.synchronizedList(new ArrayList<SettingsSavingComponent>());
@Nullable private SaveSessionImpl mySession;
@@ -53,9 +52,8 @@ public abstract class ComponentStoreImpl implements IComponentStore {
return getStateStorageManager().getStateStorage(storageSpec);
}
- protected StateStorage getDefaultsStorage() {
- throw new UnsupportedOperationException("Method getDefaultsStorage is not supported in " + getClass());
- }
+ @Nullable
+ protected abstract StateStorage getDefaultsStorage();
@Override
public void initComponent(@NotNull final Object component, final boolean service) {
@@ -143,12 +141,10 @@ public abstract class ComponentStoreImpl implements IComponentStore {
private <T> void commitPersistentComponent(@NotNull final PersistentStateComponent<T> persistentStateComponent,
@NotNull StateStorageManager.ExternalizationSession session) {
- Storage[] storageSpecs = getComponentStorageSpecs(persistentStateComponent, StateStorageOperation.WRITE);
-
T state = persistentStateComponent.getState();
if (state != null) {
- session
- .setState(storageSpecs, persistentStateComponent, getComponentName(persistentStateComponent), state);
+ Storage[] storageSpecs = getComponentStorageSpecs(persistentStateComponent, StateStorageOperation.WRITE);
+ session.setState(storageSpecs, persistentStateComponent, getComponentName(persistentStateComponent), state);
}
}
@@ -276,13 +272,12 @@ public abstract class ComponentStoreImpl implements IComponentStore {
@NotNull
private static <T> Class<T> getComponentStateClass(@NotNull final PersistentStateComponent<T> persistentStateComponent) {
final Class persistentStateComponentClass = PersistentStateComponent.class;
+
Class componentClass = persistentStateComponent.getClass();
nextSuperClass:
while (true) {
- final Class[] interfaces = componentClass.getInterfaces();
-
- for (Class anInterface : interfaces) {
+ for (Class anInterface : componentClass.getInterfaces()) {
if (anInterface.equals(persistentStateComponentClass)) {
break nextSuperClass;
}
@@ -292,7 +287,7 @@ public abstract class ComponentStoreImpl implements IComponentStore {
}
final Type type = ReflectionUtil.resolveVariable(persistentStateComponentClass.getTypeParameters()[0], componentClass);
-
+ assert type != null;
//noinspection unchecked
return (Class<T>)ReflectionUtil.getRawType(type);
}
@@ -319,14 +314,12 @@ public abstract class ComponentStoreImpl implements IComponentStore {
protected <T> Storage[] getComponentStorageSpecs(@NotNull final PersistentStateComponent<T> persistentStateComponent,
final StateStorageOperation operation) throws StateStorageException {
final State stateSpec = getStateSpec(persistentStateComponent);
-
final Storage[] storages = stateSpec.storages();
-
- if (storages.length == 1) return storages;
-
+ if (storages.length == 1) {
+ return storages;
+ }
assert storages.length > 0;
-
final Class<StorageAnnotationsDefaultValues.NullStateStorageChooser> defaultClass =
StorageAnnotationsDefaultValues.NullStateStorageChooser.class;
@@ -340,14 +333,11 @@ public abstract class ComponentStoreImpl implements IComponentStore {
}
else {
try {
- //noinspection unchecked
- final StateStorageChooser<PersistentStateComponent<T>> storageChooser = storageChooserClass.newInstance();
+ @SuppressWarnings("unchecked")
+ StateStorageChooser<PersistentStateComponent<T>> storageChooser = ReflectionUtil.newInstance(storageChooserClass);
return storageChooser.selectStorages(storages, persistentStateComponent, operation);
}
- catch (InstantiationException e) {
- throw new StateStorageException(e);
- }
- catch (IllegalAccessException e) {
+ catch (RuntimeException e) {
throw new StateStorageException(e);
}
}
@@ -404,7 +394,7 @@ public abstract class ComponentStoreImpl implements IComponentStore {
}
catch (StateStorageException e) {
LOG.info(e);
- throw new IOException(e.getMessage());
+ throw new IOException(e.getMessage(), e);
}
return this;
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
index 48247b2de866..6f0c3b8122cf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
@@ -159,8 +159,8 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
}
@Override
- public String expandMacros(final String file) {
- throw new UnsupportedOperationException("Method expandMacroses not implemented in " + getClass());
+ public String expandMacros(@NotNull String file) {
+ throw new UnsupportedOperationException("Method expandMacros not implemented in " + getClass());
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
index 574823767d9b..2120030db2c1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
@@ -55,7 +55,7 @@ final class OldStreamProviderAdapter extends StreamProvider implements CurrentUs
}
@Override
- public void deleteFile(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
+ public void delete(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
if (myRoamingType == roamingType) {
myProvider.deleteFile(fileSpec, roamingType);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
index f6a4e11e5aa5..0eed50a65131 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.project.impl.ProjectImpl;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -47,6 +48,7 @@ class ProjectStateStorageManager extends StateStorageManagerImpl {
return new ProjectStoreImpl.IprStorageData(ROOT_TAG_NAME, myProject);
}
+ @Nullable
@Override
protected String getOldStorageSpec(Object component, final String componentName, final StateStorageOperation operation) throws
StateStorageException {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
index 0e2828e988a3..68d882d2b204 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
@@ -58,7 +58,7 @@ public interface StateStorageManager {
StateStorage getOldStorage(Object component, String componentName, StateStorageOperation operation) throws StateStorageException;
@Nullable
- String expandMacros(String file);
+ String expandMacros(@NotNull String file);
@Deprecated
void registerStreamProvider(@SuppressWarnings("deprecation") StreamProvider streamProvider, final RoamingType type);
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
index 1b7da8fc2144..431c9a97820c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
@@ -331,7 +331,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Override
@Nullable
- public synchronized String expandMacros(final String file) {
+ public synchronized String expandMacros(@NotNull String file) {
final Matcher matcher = MACRO_PATTERN.matcher(file);
while (matcher.find()) {
String m = matcher.group(1);
@@ -427,6 +427,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
return getFileStateStorage(getOldStorageSpec(component, componentName, operation));
}
+ @Nullable
protected abstract String getOldStorageSpec(Object component, final String componentName, final StateStorageOperation operation)
throws StateStorageException;
@@ -615,11 +616,11 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
@Override
- public void deleteFile(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
+ public void delete(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
for (StreamProvider streamProvider : myStreamProviders) {
try {
if (streamProvider.isEnabled() && streamProvider.isApplicable(fileSpec, roamingType)) {
- streamProvider.deleteFile(fileSpec, roamingType);
+ streamProvider.delete(fileSpec, roamingType);
}
}
catch (Exception e) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
index 73aea37d6444..bd732705446a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
@@ -113,19 +113,25 @@ public class StorageUtil {
@Nullable
static VirtualFile save(@NotNull IFile file, Parent element, Object requestor) throws StateStorageException {
try {
- VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
- Couple<String> pair = loadFile(vFile);
- String text = JDOMUtil.writeParent(element, pair.second);
-
+ String lineSeparator;
+ String oldText;
if (file.exists()) {
- if (text.equals(pair.first)) {
- return null;
- }
+ VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
+ Couple<String> pair = loadFile(vFile);
+ lineSeparator = pair.second;
+ oldText = pair.first;
}
else {
+ oldText = null;
+ lineSeparator = SystemProperties.getLineSeparator();
file.createParentDirs();
}
+ String text = JDOMUtil.writeParent(element, lineSeparator);
+ if (text.equals(oldText)) {
+ return null;
+ }
+
// mark this action as modifying the file which daemon analyzer should ignore
AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(DocumentRunnable.IgnoreDocumentRunnable.class);
try {
@@ -245,6 +251,7 @@ public class StorageUtil {
}
}
+ @NotNull
public static BufferExposingByteArrayOutputStream documentToBytes(@NotNull Document document, boolean useSystemLineSeparator) throws IOException {
BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(512);
OutputStreamWriter writer = new OutputStreamWriter(out, CharsetToolkit.UTF8_CHARSET);
@@ -271,9 +278,9 @@ public class StorageUtil {
}
}
- public static void deleteContent(@NotNull StreamProvider provider, @NotNull String fileSpec, @NotNull RoamingType type) {
+ public static void delete(@NotNull StreamProvider provider, @NotNull String fileSpec, @NotNull RoamingType type) {
if (provider.isApplicable(fileSpec, type)) {
- provider.deleteFile(fileSpec, type);
+ provider.delete(fileSpec, type);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
index cf77ee377cf1..ec57d8c63601 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
@@ -47,5 +47,8 @@ public abstract class StreamProvider {
return Collections.emptyList();
}
- public abstract void deleteFile(@NotNull String fileSpec, @NotNull RoamingType roamingType);
+ /**
+ * Delete file or directory
+ */
+ public abstract void delete(@NotNull String fileSpec, @NotNull RoamingType roamingType);
} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java b/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java
new file mode 100644
index 000000000000..b508686ade00
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationStarterEx;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.StreamUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"})
+public abstract class ApplicationStarterBase extends ApplicationStarterEx {
+ private final String myCommandName;
+ private final int[] myArgsCount;
+
+ protected ApplicationStarterBase(String commandName, int... possibleArgumentsCount) {
+ myCommandName = commandName;
+ myArgsCount = possibleArgumentsCount;
+ }
+
+ @Override
+ public String getCommandName() {
+ return myCommandName;
+ }
+
+ @Override
+ public boolean isHeadless() {
+ return false;
+ }
+
+ @Override
+ public void processExternalCommandLine(String[] args) {
+ if (!checkArguments(args)) {
+ Messages.showMessageDialog(getUsageMessage(), StringUtil.toTitleCase(getCommandName()), Messages.getInformationIcon());
+ return;
+ }
+ try {
+ processCommand(args);
+ }
+ catch (Exception e) {
+ Messages.showMessageDialog(String.format("Error showing %s: %s", getCommandName(), e.getMessage()),
+ StringUtil.toTitleCase(getCommandName()),
+ Messages.getErrorIcon());
+ }
+ finally {
+ saveAll();
+ }
+ }
+
+ private static void saveAll() {
+ FileDocumentManager.getInstance().saveAllDocuments();
+ ApplicationManager.getApplication().saveSettings();
+ }
+
+ private boolean checkArguments(String[] args) {
+ return Arrays.binarySearch(myArgsCount, args.length - 1) != -1 && getCommandName().equals(args[0]);
+ }
+
+ public abstract String getUsageMessage();
+
+ protected abstract void processCommand(String[] args) throws Exception;
+
+ @Override
+ public void premain(String[] args) {
+ if (!checkArguments(args)) {
+ System.err.println(getUsageMessage());
+ System.exit(1);
+ }
+ }
+
+ @Override
+ public void main(String[] args) {
+ try {
+ processCommand(args);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(2);
+ }
+ finally {
+ saveAll();
+ }
+
+ System.exit(0);
+ }
+
+ public static VirtualFile findOrCreateFile(String path) throws IOException {
+ final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
+ if (file == null) {
+ boolean result = new File(path).createNewFile();
+ if (result) {
+ return findFile(path);
+ }
+ else {
+ throw new FileNotFoundException("Can't create file " + path);
+ }
+ }
+ return file;
+ }
+
+ /**
+ * Get direct from file because IDEA cache files(see #IDEA-81067)
+ */
+ public static String getText(VirtualFile file) throws IOException {
+ FileInputStream inputStream = new FileInputStream(file.getPath());
+ try {
+ return StreamUtil.readText(inputStream);
+ }
+ finally {
+ inputStream.close();
+ }
+ }
+
+ public static boolean haveDirs(VirtualFile... files) {
+ for (VirtualFile file : files) {
+ if (file.isDirectory()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean areJars(VirtualFile file1, VirtualFile file2) {
+ return JarFileSystem.PROTOCOL.equalsIgnoreCase(file1.getExtension()) && JarFileSystem.PROTOCOL.equalsIgnoreCase(file2.getExtension());
+ }
+
+ public static boolean areDirs(VirtualFile file1, VirtualFile file2) {
+ return file1.isDirectory() && file2.isDirectory();
+ }
+
+ public static class OperationFailedException extends IOException {
+ public OperationFailedException(@NotNull String message) {
+ super(message);
+ }
+ }
+
+ @NotNull
+ public static VirtualFile findFile(final String path) throws OperationFailedException {
+ File ioFile = new File(path);
+ if (!ioFile.exists()) {
+ final String dir = PathManager.getOriginalWorkingDir();
+ ioFile = new File(dir + File.separator + path);
+ }
+ final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
+ if (file == null) {
+ throw new OperationFailedException("Can't find file " + path);
+ }
+ return file;
+ }
+
+ @Override
+ public boolean canProcessExternalCommandLine() {
+ return true;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java b/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java
new file mode 100644
index 000000000000..742a405f350e
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff;
+
+import com.intellij.ide.diff.DiffElement;
+import com.intellij.ide.diff.DirDiffSettings;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.fileTypes.UnknownFileType;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.vfs.VirtualFile;
+
+/**
+ * @author max
+ * @author Konstantin Bulenkov
+ */
+@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"})
+public class DiffApplication extends ApplicationStarterBase {
+ public DiffApplication() {
+ super("diff", 2);
+ }
+
+ public String getUsageMessage() {
+ final String scriptName = ApplicationNamesInfo.getInstance().getScriptName();
+ return DiffBundle.message("diff.application.usage.parameters.and.description", scriptName);
+ }
+
+ public void processCommand(String[] args) throws OperationFailedException {
+ final String path1 = args[1];
+ final String path2 = args[2];
+ final VirtualFile file1 = findFile(path1);
+ final VirtualFile file2 = findFile(path2);
+ final boolean areDirs = areDirs(file1, file2);
+ final boolean areJars = areJars(file1, file2);
+ if (areDirs || areJars) {
+ final DirDiffManager diffManager = DirDiffManager.getInstance(ProjectManager.getInstance().getDefaultProject());
+ final DiffElement d1 = diffManager.createDiffElement(file1);
+ final DiffElement d2 = diffManager.createDiffElement(file2);
+ if (d1 == null) {
+ throw new OperationFailedException(DiffBundle.message("cannot.create.diff.error", path1));
+ }
+ if (d2 == null) {
+ throw new OperationFailedException(DiffBundle.message("cannot.create.diff.error", path1));
+ }
+ else if (!diffManager.canShow(d1, d2)) {
+ throw new OperationFailedException(DiffBundle.message("cannot.compare.error", path1, path2));
+ }
+
+ final DirDiffSettings settings = new DirDiffSettings();
+ settings.showInFrame = false;
+ diffManager.showDiff(d1, d2, settings, null);
+ }
+ else {
+ file1.refresh(false, false);
+ file2.refresh(false, false);
+
+ if (file1.getFileType() == UnknownFileType.INSTANCE) {
+ throw new OperationFailedException(DiffBundle.message("unknown.file.type.error", path1));
+ }
+ else if (file2.getFileType() == UnknownFileType.INSTANCE) {
+ throw new OperationFailedException(DiffBundle.message("unknown.file.type.error", path2));
+ }
+
+ SimpleDiffRequest request = SimpleDiffRequest.compareFiles(file1, file2, ProjectManager.getInstance().getDefaultProject());
+ request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG);
+ DiffManager.getInstance().getIdeaDiffTool().show(request);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java b/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java
new file mode 100644
index 000000000000..0c088929ea49
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.diff;
+
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.vfs.VirtualFile;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class MergeApplication extends ApplicationStarterBase {
+ public MergeApplication() {
+ super("merge", 3 ,4);
+ }
+
+ @Override
+ public String getUsageMessage() {
+ final String script = ApplicationNamesInfo.getInstance().getScriptName();
+ return String.format("Usage:\n\t%s merge <file1> <file2> <original>\n\t%s merge <file1> <file2> <original> <output>", script, script);
+ }
+
+ @Override
+ protected void processCommand(String[] args) throws Exception {
+ final VirtualFile left = findFile(args[1]);
+ final VirtualFile right = findFile(args[2]);
+ final VirtualFile middle = findFile(args[3]);
+ final VirtualFile result = findOrCreateFile(args.length == 4 ? args[3] : args[4]);
+
+ MergeRequest request = DiffRequestFactory.getInstance()
+ .createMergeRequest(getText(left), getText(right), getText(middle), result,
+ ProjectManager.getInstance().getDefaultProject(),
+ ActionButtonPresentation.APPLY,
+ ActionButtonPresentation.CANCEL_WITH_PROMPT);
+ request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG);
+ request.setWindowTitle("Merge");
+ request.setVersionTitles(new String[]{left.getPresentableUrl(), result.getPresentableUrl(), middle.getPresentableUrl()});
+ DiffManager.getInstance().getDiffTool().show(request);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
index ec7a316357e2..3ad1a58a6732 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
@@ -93,7 +93,7 @@ public class DiffPanelOptions {
while (window instanceof DialogWrapperDialog) {
DialogWrapperDialog dlg = (DialogWrapperDialog)window;
window = window.getParent();
- dlg.getDialogWrapper().close(DialogWrapper.CLOSE_EXIT_CODE);
+ dlg.getDialogWrapper().doCancelAction();
}
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
index 2a5a01b43ca5..a67a6ad5af71 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.diff.impl;
+import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.DiffContentUtil;
@@ -84,11 +85,22 @@ public class DiffUtil {
}
public static EditorEx createEditor(Document document, Project project, boolean isViewer) {
+ return createEditor(document, project, isViewer, null);
+ }
+
+ public static EditorEx createEditor(Document document, Project project, boolean isViewer, @Nullable FileType fileType) {
EditorFactory factory = EditorFactory.getInstance();
EditorEx editor = (EditorEx)(isViewer ? factory.createViewer(document, project) : factory.createEditor(document, project));
editor.putUserData(DiffManagerImpl.EDITOR_IS_DIFF_KEY, Boolean.TRUE);
editor.setSoftWrapAppliancePlace(SoftWrapAppliancePlaces.VCS_DIFF);
editor.getGutterComponentEx().revalidateMarkup();
+
+ if (fileType != null && project != null && !project.isDisposed()) {
+ CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project);
+ editor.getSettings().setTabSize(codeStyleFacade.getTabSize(fileType));
+ editor.getSettings().setUseTabCharacter(codeStyleFacade.useTabCharacter(fileType));
+ }
+
return editor;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java
index 9ae17ec50df0..d4fbf23aa6c4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java
@@ -46,7 +46,7 @@ abstract class BaseExternalTool implements DiffTool {
myToolProperty = toolProperty;
}
- public final boolean canShow(DiffRequest request) {
+ public final boolean canShow(@NotNull DiffRequest request) {
if (!isEnabled() || StringUtil.isEmpty(getToolPath())) return false;
return isAvailable(request);
}
@@ -56,10 +56,10 @@ abstract class BaseExternalTool implements DiffTool {
return null;
}
- public abstract boolean isAvailable(DiffRequest request);
+ public abstract boolean isAvailable(@NotNull DiffRequest request);
@Nullable
- protected ContentExternalizer externalize(final DiffRequest request, final int index) {
+ protected ContentExternalizer externalize(@NotNull DiffRequest request, final int index) {
final VirtualFile file = getLocalFile(request.getContents()[index].getFile());
if (LocalFileExternalizer.canExternalizeAsFile(file)) {
@@ -81,7 +81,8 @@ abstract class BaseExternalTool implements DiffTool {
return myEnableProperty.value(getProperties());
}
- protected List<String> getParameters(DiffRequest request) throws Exception {
+ @NotNull
+ protected List<String> getParameters(@NotNull DiffRequest request) throws Exception {
final String p1 = convertToPath(request, 0);
final String p2 = convertToPath(request, 1);
final List<String> params = new ArrayList<String>();
@@ -91,12 +92,8 @@ abstract class BaseExternalTool implements DiffTool {
}
public void show(DiffRequest request) {
- for (DiffContent diffContent : request.getContents()) {
- Document document = diffContent.getDocument();
- if (document != null) {
- FileDocumentManager.getInstance().saveDocument(document);
- }
- }
+ saveContents(request);
+
GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath(getToolPath());
try {
@@ -109,6 +106,15 @@ abstract class BaseExternalTool implements DiffTool {
}
}
+ protected void saveContents(DiffRequest request) {
+ for (DiffContent diffContent : request.getContents()) {
+ Document document = diffContent.getDocument();
+ if (document != null) {
+ FileDocumentManager.getInstance().saveDocument(document);
+ }
+ }
+ }
+
@Nullable
protected String convertToPath(DiffRequest request, int index) throws Exception {
final ContentExternalizer externalize = externalize(request, index);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFiles.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFiles.java
index 0594ab09c0c5..6f661acf9463 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFiles.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFiles.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.diff.impl.DiffUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
@@ -30,7 +31,7 @@ class ExtCompareFiles extends BaseExternalTool {
super(DiffManagerImpl.ENABLE_FILES, DiffManagerImpl.FILES_TOOL);
}
- public boolean isAvailable(DiffRequest request) {
+ public boolean isAvailable(@NotNull DiffRequest request) {
final DiffContent[] contents = request.getContents();
for (DiffContent content : contents) {
final VirtualFile file = getLocalFile(content.getFile());
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFolders.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFolders.java
index 14c0a9607293..6260176d3e26 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFolders.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtCompareFolders.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.diff.impl.external;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -31,7 +32,7 @@ class ExtCompareFolders extends BaseExternalTool {
}
@Override
- public boolean isAvailable(DiffRequest request) {
+ public boolean isAvailable(@NotNull DiffRequest request) {
final DiffContent[] contents = request.getContents();
if (contents.length != 2) return false;
if (externalize(request, 0) == null) return false;
@@ -40,7 +41,7 @@ class ExtCompareFolders extends BaseExternalTool {
}
@Nullable
- protected ContentExternalizer externalize(DiffRequest request, int index) {
+ protected ContentExternalizer externalize(@NotNull DiffRequest request, int index) {
final VirtualFile file = request.getContents()[index].getFile();
if (!isLocalDirectory(file)) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtMergeFiles.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtMergeFiles.java
index 82313a5c9c35..cfee691a1f1f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtMergeFiles.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ExtMergeFiles.java
@@ -15,10 +15,21 @@
*/
package com.intellij.openapi.diff.impl.external;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.util.ExecutionErrorDialog;
+import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.DiffRequest;
import com.intellij.openapi.diff.impl.mergeTool.MergeRequestImpl;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.TimeoutUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -34,7 +45,8 @@ public class ExtMergeFiles extends BaseExternalTool {
}
@Override
- public boolean isAvailable(DiffRequest request) {
+ public boolean isAvailable(@NotNull DiffRequest request) {
+ if (!(request instanceof MergeRequestImpl)) return false;
DiffContent[] contents = request.getContents();
if (contents.length != 3) return false;
if (externalize(request, 0) == null) return false;
@@ -45,7 +57,8 @@ public class ExtMergeFiles extends BaseExternalTool {
}
@Override
- protected List<String> getParameters(DiffRequest request) throws Exception {
+ @NotNull
+ protected List<String> getParameters(@NotNull DiffRequest request) throws Exception {
final List<String> params = new ArrayList<String>();
String result = ((MergeRequestImpl)request).getResultContent().getFile().getPath();
String left = externalize(request, 0).getContentFile().getPath();
@@ -60,4 +73,41 @@ public class ExtMergeFiles extends BaseExternalTool {
}
return params;
}
+
+ @Override
+ public void show(@NotNull DiffRequest request) {
+ saveContents(request);
+
+ int result = DialogWrapper.CANCEL_EXIT_CODE;
+
+ GeneralCommandLine commandLine = new GeneralCommandLine();
+ commandLine.setExePath(getToolPath());
+ try {
+ commandLine.addParameters(getParameters(request));
+ commandLine.createProcess();
+
+ ProgressManager.getInstance().run(new Task.Modal(request.getProject(), "Launching external tool", false) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ TimeoutUtil.sleep(1000);
+ }
+ });
+
+ if (Messages.YES == Messages.showYesNoDialog(request.getProject(),
+ "Press \"Mark as Resolved\" when you finish resolving conflicts in the external tool",
+ "Merge In External Tool", "Mark as Resolved", "Revert", null)) {
+ result = DialogWrapper.OK_EXIT_CODE;
+ }
+ ((MergeRequestImpl)request).getResultContent().getFile().refresh(false, false);
+ // We can actually check exit code of external tool, but some of them could work with tabs -> do not close at all
+ }
+ catch (Exception e) {
+ ExecutionErrorDialog
+ .show(new ExecutionException(e.getMessage()), DiffBundle.message("cant.launch.diff.tool.error.message"), request.getProject());
+ }
+ finally {
+ ((MergeRequestImpl)request).setResult(result);
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/EditorPlaceHolder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/EditorPlaceHolder.java
index 0632b56d0f0e..dabaf5f1f030 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/EditorPlaceHolder.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/EditorPlaceHolder.java
@@ -93,7 +93,7 @@ class EditorPlaceHolder extends DiffMarkup implements DiffVersionComponent {
} else {
document = new DocumentImpl("Can not show", true);
final EditorFactory editorFactory = EditorFactory.getInstance();
- myEditor = DiffUtil.createEditor(document, getProject(), true);
+ myEditor = DiffUtil.createEditor(document, getProject(), true, content.getContentType());
addDisposable(new Disposable() {
public void dispose() {
editorFactory.releaseEditor(myEditor);
@@ -105,7 +105,7 @@ class EditorPlaceHolder extends DiffMarkup implements DiffVersionComponent {
}
else {
final EditorFactory editorFactory = EditorFactory.getInstance();
- myEditor = DiffUtil.createEditor(document, getProject(), false);
+ myEditor = DiffUtil.createEditor(document, getProject(), false, content.getContentType());
addDisposable(new Disposable() {
public void dispose() {
editorFactory.releaseEditor(myEditor);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
index f6cd904c9503..3bc3e90b81b3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/util/SyncScrollSupport.java
@@ -136,16 +136,13 @@ public class SyncScrollSupport implements Disposable {
Editor slaveEditor = sidesContainer.getEditor(masterSide.otherSide());
if (slaveEditor == null) return;
- ScrollingModel scrollingModel = slaveEditor.getScrollingModel();
- scrollingModel.disableAnimation();
- scrollingModel.scrollHorizontally(newScrollOffset);
- scrollingModel.enableAnimation();
+ doScrollHorizontally(slaveEditor.getScrollingModel(), newScrollOffset);
}
private static void syncVerticalScroll(@NotNull ScrollingContext context,
@NotNull Rectangle newRectangle,
@NotNull Rectangle oldRectangle) {
- if (newRectangle.y == oldRectangle.y && newRectangle.height == oldRectangle.height) return;
+ if (newRectangle.y == oldRectangle.y) return;
EditingSides sidesContainer = context.getSidesContainer();
FragmentSide masterSide = context.getMasterSide();
FragmentSide masterDiffSide = context.getMasterDiffSide();
@@ -155,42 +152,55 @@ public class SyncScrollSupport implements Disposable {
if (master == null || slave == null) return;
+ int masterVerticalScrollOffset = master.getScrollingModel().getVerticalScrollOffset();
+ int slaveVerticalScrollOffset = slave.getScrollingModel().getVerticalScrollOffset();
+
Rectangle viewRect = master.getScrollingModel().getVisibleArea();
int middleY = viewRect.height / 3;
- int masterVerticalScrollOffset = getScrollOffset(master);
- int slaveVerticalScrollOffset = getScrollOffset(slave);
+ if (master.getDocument().getTextLength() == 0) return;
LogicalPosition masterPos = master.xyToLogicalPosition(new Point(viewRect.x, masterVerticalScrollOffset + middleY));
int masterCenterLine = masterPos.line;
- if (masterCenterLine > master.getDocument().getLineCount()) {
- masterCenterLine = master.getDocument().getLineCount();
+ int scrollToLine = sidesContainer.getLineBlocks().transform(masterDiffSide, masterCenterLine);
+
+ int offset;
+ if (scrollToLine < 0) {
+ offset = slaveVerticalScrollOffset + newRectangle.y - oldRectangle.y;
}
- int scrollToLine = sidesContainer.getLineBlocks().transform(masterDiffSide, masterCenterLine) + 1;
- int actualLine = scrollToLine - 1;
+ else {
+ int correction = (masterVerticalScrollOffset + middleY) % master.getLineHeight();
+ Point point = slave.logicalPositionToXY(new LogicalPosition(scrollToLine, masterPos.column));
+ offset = point.y - middleY + correction;
+ }
+
+ int deltaHeaderOffset = getHeaderOffset(slave) - getHeaderOffset(master);
+ doScrollVertically(slave.getScrollingModel(), offset + deltaHeaderOffset);
+ }
+ private static int getHeaderOffset(@NotNull final Editor editor) {
+ final JComponent header = editor.getHeaderComponent();
+ return header == null ? 0 : header.getHeight();
+ }
- slave.getScrollingModel().disableAnimation();
+ private static void doScrollVertically(@NotNull ScrollingModel model, int offset) {
+ model.disableAnimation();
try {
- if (scrollToLine <= 0) {
- int offset = newRectangle.y - oldRectangle.y;
- slave.getScrollingModel().scrollVertically(slaveVerticalScrollOffset + offset);
- }
- else {
- int correction = (masterVerticalScrollOffset + middleY) % master.getLineHeight();
- Point point = slave.logicalPositionToXY(new LogicalPosition(actualLine, masterPos.column));
- slave.getScrollingModel().scrollVertically(point.y - middleY + correction);
- }
- } finally {
- slave.getScrollingModel().enableAnimation();
+ model.scrollVertically(offset);
+ }
+ finally {
+ model.enableAnimation();
}
}
- private static int getScrollOffset(@NotNull final Editor editor) {
- final JComponent header = editor.getHeaderComponent();
- int headerOffset = header == null ? 0 : header.getHeight();
-
- return editor.getScrollingModel().getVerticalScrollOffset() - headerOffset;
+ private static void doScrollHorizontally(@NotNull ScrollingModel model, int offset) {
+ model.disableAnimation();
+ try {
+ model.scrollHorizontally(offset);
+ }
+ finally {
+ model.enableAnimation();
+ }
}
public static void scrollEditor(@NotNull Editor editor, int logicalLine) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
index 452d7e144356..cf3c196a9d78 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ExportableComponent;
import com.intellij.openapi.components.NamedComponent;
import com.intellij.openapi.components.RoamingType;
+import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.colors.EditorColorsListener;
@@ -67,7 +68,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name
private final DefaultColorSchemesManager myDefaultColorSchemesManager;
private final SchemesManager<EditorColorsScheme, EditorColorsSchemeImpl> mySchemesManager;
@NonNls private static final String NAME_ATTR = "name";
- private static final String FILE_SPEC = "$ROOT_CONFIG$/colors";
+ private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/colors";
private static final String FILE_EXT = ".icls";
public EditorColorsManagerImpl(DefaultColorSchemesManager defaultColorSchemesManager, SchemesManagerFactory schemesManagerFactory) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
index 216429557cea..7d9973fed2d3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
@@ -407,7 +407,7 @@ public final class EditorUtil {
IterationState state = new IterationState(editorImpl, start, end, false);
int fontType = state.getMergedAttributes().getFontType();
int column = currentColumn[0];
- int spaceSize = getSpaceWidth(fontType, editorImpl);
+ int plainSpaceSize = getSpaceWidth(Font.PLAIN, editorImpl);
for (; column < columnNumber && offset < end; offset++) {
if (offset >= state.getEndOffset()) {
state.advance();
@@ -417,7 +417,7 @@ public final class EditorUtil {
char c = text.charAt(offset);
if (c == '\t') {
final int newX = nextTabStop(x, editorImpl);
- final int columns = columnsNumber(newX - x, spaceSize);
+ final int columns = columnsNumber(newX - x, plainSpaceSize);
if (debugBuffer != null) {
debugBuffer.append(String.format(
"Processing tabulation at the offset %d. Current X: %d, new X: %d, current column: %d, new column: %d%n",
@@ -556,11 +556,11 @@ public final class EditorUtil {
return nextTabStop(x, getSpaceWidth(Font.PLAIN, editor), tabSize);
}
- public static int nextTabStop(int x, int spaceWidth, int tabSize) {
+ public static int nextTabStop(int x, int plainSpaceWidth, int tabSize) {
if (tabSize <= 0) {
- return x + spaceWidth;
+ return x + plainSpaceWidth;
}
- tabSize *= spaceWidth;
+ tabSize *= plainSpaceWidth;
int nTabs = x / tabSize;
return (nTabs + 1) * tabSize;
@@ -617,15 +617,15 @@ public final class EditorUtil {
* @param c target char
* @param x <code>'x'</code> coordinate of the line where given char is represented that indicates char end location
* @param prevX <code>'x'</code> coordinate of the line where given char is represented that indicates char start location
- * @param spaceSize <code>'space'</code> symbol width
+ * @param plainSpaceSize <code>'space'</code> symbol width (in plain font style)
* @return number of columns necessary for representation of the given char on a screen.
*/
- public static int columnsNumber(char c, int x, int prevX, int spaceSize) {
+ public static int columnsNumber(char c, int x, int prevX, int plainSpaceSize) {
if (c != '\t') {
return 1;
}
- int result = (x - prevX) / spaceSize;
- if ((x - prevX) % spaceSize > 0) {
+ int result = (x - prevX) / plainSpaceSize;
+ if ((x - prevX) % plainSpaceSize > 0) {
result++;
}
return result;
@@ -635,12 +635,12 @@ public final class EditorUtil {
* Allows to answer how many visual columns are occupied by the given width.
*
* @param width target width
- * @param spaceSize width of the single space symbol within the target editor
+ * @param plainSpaceSize width of the single space symbol within the target editor (in plain font style)
* @return number of visual columns are occupied by the given width
*/
- public static int columnsNumber(int width, int spaceSize) {
- int result = width / spaceSize;
- if (width % spaceSize > 0) {
+ public static int columnsNumber(int width, int plainSpaceSize) {
+ int result = width / plainSpaceSize;
+ if (width % plainSpaceSize > 0) {
result++;
}
return result;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
index c769f92fff78..e2693b2c835f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
@@ -1156,7 +1156,13 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
@Override
public void setSelection(int startOffset, int endOffset) {
- doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false);
+ setSelection(startOffset, endOffset, true);
+ }
+
+ @Override
+ public void setSelection(int startOffset, int endOffset, boolean updateSystemSelection) {
+ doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false,
+ updateSystemSelection);
}
@Override
@@ -1173,16 +1179,22 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
@Override
public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ setSelection(startPosition, startOffset, endPosition, endOffset, true);
+ }
+
+ @Override
+ public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset, boolean updateSystemSelection) {
VisualPosition startPositionToUse = startPosition == null ? myEditor.offsetToVisualPosition(startOffset) : startPosition;
VisualPosition endPositionToUse = endPosition == null ? myEditor.offsetToVisualPosition(endOffset) : endPosition;
- doSetSelection(startPositionToUse, startOffset, endPositionToUse, endOffset, true);
+ doSetSelection(startPositionToUse, startOffset, endPositionToUse, endOffset, true, updateSystemSelection);
}
private void doSetSelection(@NotNull final VisualPosition startPosition,
final int _startOffset,
@NotNull final VisualPosition endPosition,
final int _endOffset,
- final boolean visualPositionAware)
+ final boolean visualPositionAware,
+ final boolean updateSystemSelection)
{
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
public void run() {
@@ -1278,7 +1290,9 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
myEditor.getSelectionModel().fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset);
- updateSystemSelection();
+ if (updateSystemSelection) {
+ updateSystemSelection();
+ }
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
index 8d6608e63dd9..15a907e826e4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
@@ -443,6 +443,11 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
@Override
public void setCaretsAndSelections(@NotNull final List<CaretState> caretStates) {
+ setCaretsAndSelections(caretStates, true);
+ }
+
+ @Override
+ public void setCaretsAndSelections(@NotNull final List<CaretState> caretStates, final boolean updateSystemSelection) {
myEditor.assertIsDispatchThread();
if (caretStates.isEmpty()) {
throw new IllegalArgumentException("At least one caret should exist");
@@ -474,9 +479,11 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
caret.moveToLogicalPosition(caretState.getCaretPosition());
}
if (caretState != null && caretState.getSelectionStart() != null && caretState.getSelectionEnd() != null) {
- caret.setSelection(myEditor.logicalToVisualPosition(caretState.getSelectionStart()), myEditor.logicalPositionToOffset(caretState.getSelectionStart()),
- myEditor.logicalToVisualPosition(caretState.getSelectionEnd()), myEditor.logicalPositionToOffset(
- caretState.getSelectionEnd()));
+ caret.setSelection(myEditor.logicalToVisualPosition(caretState.getSelectionStart()),
+ myEditor.logicalPositionToOffset(caretState.getSelectionStart()),
+ myEditor.logicalToVisualPosition(caretState.getSelectionEnd()),
+ myEditor.logicalPositionToOffset(caretState.getSelectionEnd()),
+ updateSystemSelection);
}
}
int caretsToRemove = myCarets.size() - caretStates.size();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ContextMenuImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ContextMenuImpl.java
index 28a7c2204265..cbe6da5379cf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ContextMenuImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ContextMenuImpl.java
@@ -46,16 +46,15 @@ import java.awt.event.ActionListener;
public class ContextMenuImpl extends JPanel implements Disposable {
@NonNls
public static final String ACTION_GROUP = "EditorContextBarMenu";
-
- private ActionGroup myActionGroup;
private final JComponent myComponent;
+ private final JLayeredPane myLayeredPane;
+ private ActionGroup myActionGroup;
private boolean myVisible = false;
private boolean myShow = false;
private int myCurrentOpacity;
private Timer myTimer;
private EditorImpl myEditor;
private boolean myDisposed;
- private final JLayeredPane myLayeredPane;
private ActionToolbar myActionToolbar;
public ContextMenuImpl(JLayeredPane layeredPane, @NotNull final JScrollPane container, @NotNull final EditorImpl editor) {
@@ -81,7 +80,7 @@ public class ContextMenuImpl extends JPanel implements Disposable {
}
});
- AnAction action = actionManager.getAction("EditorContextBarMenu");
+ AnAction action = actionManager.getAction(ACTION_GROUP);
if (action == null) {
action = new DefaultActionGroup();
actionManager.registerAction(ACTION_GROUP, action);
@@ -107,6 +106,15 @@ public class ContextMenuImpl extends JPanel implements Disposable {
return activationArea.contains(p.x, p.y - viewPosition.y);
}
+ public static boolean mayShowToolbar(@Nullable final Document document) {
+ if (document == null) {
+ return false;
+ }
+
+ final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+ return file != null && file.isValid() && (file.isInLocalFileSystem() || file instanceof HttpVirtualFile);
+ }
+
private void toggleContextToolbar(final boolean show) {
final Component toolbar = myComponent.getComponent(0);
final int count = ((Container)toolbar).getComponentCount();
@@ -201,15 +209,6 @@ public class ContextMenuImpl extends JPanel implements Disposable {
}
}
- public static boolean mayShowToolbar(@Nullable final Document document) {
- if (document == null) {
- return false;
- }
-
- final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
- return file != null && file.isValid() && (file.isInLocalFileSystem() || file instanceof HttpVirtualFile);
- }
-
private void scheduleHide() {
if (myTimer != null && myTimer.isRunning()) {
myTimer.stop();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
index ec0cef4e76d5..d0313e04cf9f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java
@@ -203,14 +203,17 @@ public class EditorFactoryImpl extends EditorFactory implements ApplicationCompo
@Override
public void releaseEditor(@NotNull Editor editor) {
try {
- ((EditorImpl)editor).release();
+ myEditorFactoryEventDispatcher.getMulticaster().editorReleased(new EditorFactoryEvent(this, editor));
}
finally {
- myEditors.remove(editor);
- myEditorFactoryEventDispatcher.getMulticaster().editorReleased(new EditorFactoryEvent(this, editor));
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("number of Editor's:" + myEditors.size());
+ try {
+ ((EditorImpl)editor).release();
+ }
+ finally {
+ myEditors.remove(editor);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("number of Editor's:" + myEditors.size());
+ }
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index 39706f016adc..f773f842f323 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -1236,7 +1236,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
GutterIconRenderer renderer = getGutterRenderer(e);
AnAction clickAction = null;
- if (renderer != null) {
+ if (renderer != null && e.getButton() < 4) {
clickAction = (InputEvent.BUTTON2_MASK & e.getModifiers()) > 0
? renderer.getMiddleButtonClickAction()
: renderer.getClickAction();
@@ -1447,8 +1447,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
public void process(int x, int y, GutterMark renderer) {
final int ex = convertX((int)p.getX());
Icon icon = renderer.getIcon();
- if (x <= ex && ex <= x + icon.getIconWidth() &&
- y <= p.getY() && p.getY() <= y + icon.getIconHeight()) {
+ // Do not check y to extend the area where users could click
+ if (x <= ex && ex <= x + icon.getIconWidth()) {
result[0] = renderer;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index 6160ea58dcdf..51f6ec4a8cdb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -743,12 +743,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myGutterComponent.repaint(0, y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - y);
}
// make sure carets won't appear at invalid positions (e.g. on Tab width change)
- getCaretModel().runForEachCaret(new CaretAction() {
- @Override
- public void perform(Caret caret) {
- caret.moveToOffset(caret.getOffset());
- }
- });
+ for (Caret caret : getCaretModel().getAllCarets()) {
+ caret.moveToOffset(caret.getOffset());
+ }
}
private void initTabPainter() {
@@ -1153,8 +1150,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int textLength = myDocument.getTextLength();
LogicalPosition logicalPosition = visualToLogicalPosition(new VisualPosition(line, 0));
int offset = logicalPositionToOffset(logicalPosition);
+ int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this);
- if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(p.x, EditorUtil.getSpaceWidth(Font.PLAIN, this)));
+ if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize));
// There is a possible case that starting logical line is split by soft-wraps and it's part after the split should be drawn.
// We mark that we're under such circumstances then.
@@ -1172,12 +1170,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
+ "to offset %d (end offset). State: %s",
p, line, line, 0, logicalPosition, offset, line + 1, 0, endLogicalPosition, endOffset, dumpState()
));
- return new VisualPosition(line, EditorUtil.columnsNumber(p.x, EditorUtil.getSpaceWidth(Font.PLAIN, this)));
+ return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize));
}
IterationState state = new IterationState(this, offset, endOffset, false);
int fontType = state.getMergedAttributes().getFontType();
- int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
int x = 0;
int charWidth;
@@ -1221,7 +1218,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (x >= px) {
break outer;
}
- column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
+ column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize);
}
// Process 'after soft wrap' sign.
@@ -1261,7 +1258,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (x >= px) {
break;
}
- column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
+ column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize);
offset++;
}
@@ -1272,16 +1269,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
if (charWidth < 0) {
- charWidth = spaceSize;
+ charWidth = plainSpaceSize;
}
if (x >= px && c == '\t' && !onSoftWrapDrawing) {
if (mySettings.isCaretInsideTabs()) {
- column += (px - prevX) / spaceSize;
- if ((px - prevX) % spaceSize > spaceSize / 2) column++;
+ column += (px - prevX) / plainSpaceSize;
+ if ((px - prevX) % plainSpaceSize > plainSpaceSize / 2) column++;
}
else if ((x - px) * 2 < x - prevX) {
- column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
+ column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize);
}
}
else {
@@ -1290,8 +1287,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
else {
int diff = px - x;
- column += diff / spaceSize;
- if (diff % spaceSize * 2 >= spaceSize) {
+ column += diff / plainSpaceSize;
+ if (diff % plainSpaceSize * 2 >= plainSpaceSize) {
column++;
}
}
@@ -1549,7 +1546,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
// so, we can't just use 'startOffset + targetColumn' as a max end offset.
IterationState state = new IterationState(this, startOffset, calcEndOffset(startOffset, targetColumn), false);
int fontType = state.getMergedAttributes().getFontType();
- int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
+ int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this);
int column = 0;
outer:
@@ -1588,8 +1585,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (c == '\t') {
int prevX = x;
x = EditorUtil.nextTabStop(x, this);
- int columnDiff = (x - prevX) / spaceSize;
- if ((x - prevX) % spaceSize > 0) {
+ int columnDiff = (x - prevX) / plainSpaceSize;
+ if ((x - prevX) % plainSpaceSize > 0) {
// There is a possible case that tabulation symbol takes more than one visual column to represent and it's shown at
// soft-wrapped line. Soft wrap sign width may be not divisible by space size, hence, part of tabulation symbol represented
// as a separate visual column may take less space than space width.
@@ -2895,7 +2892,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
+ ", soft wraps: " + (mySoftWrapModel.isSoftWrappingEnabled() ? "on" : "off")
+ ", soft wraps data: " + getSoftWrapModel().dumpState()
+ "\n\nfolding data: " + getFoldingModel().dumpState()
- + (myDocument instanceof DocumentImpl ? "\n\ndocument info: " + ((DocumentImpl)myDocument).dumpState() : "");
+ + (myDocument instanceof DocumentImpl ? "\n\ndocument info: " + ((DocumentImpl)myDocument).dumpState() : "")
+ + "\nfont preferences: " + myScheme.getFontPreferences();
}
private class CachedFontContent {
@@ -4824,22 +4822,21 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int getDecScrollButtonHeight() {
ScrollBarUI barUI = getUI();
Insets insets = getInsets();
+ int top = Math.max(0, insets.top);
if (barUI instanceof ButtonlessScrollBarUI) {
- return insets.top + ((ButtonlessScrollBarUI)barUI).getDecrementButtonHeight();
+ return top + ((ButtonlessScrollBarUI)barUI).getDecrementButtonHeight();
}
- else if (barUI instanceof BasicScrollBarUI) {
+ if (barUI instanceof BasicScrollBarUI) {
try {
JButton decrButtonValue = (JButton)decrButtonField.get(barUI);
LOG.assertTrue(decrButtonValue != null);
- return insets.top + decrButtonValue.getHeight();
+ return top + decrButtonValue.getHeight();
}
catch (Exception exc) {
throw new IllegalStateException(exc);
}
}
- else {
- return insets.top + 15;
- }
+ return top + 15;
}
/**
@@ -6623,7 +6620,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
int fontType = state.getMergedAttributes().getFontType();
int column = 0;
int x = 0;
- int spaceSize = EditorUtil.getSpaceWidth(fontType, this);
+ int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this);
for (int i = start; i < offset; i++) {
if (i >= state.getEndOffset()) {
state.advance();
@@ -6639,7 +6636,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (c == '\t') {
int prevX = x;
x = EditorUtil.nextTabStop(x, this);
- column += EditorUtil.columnsNumber(c, x, prevX, spaceSize);
+ column += EditorUtil.columnsNumber(c, x, prevX, plainSpaceSize);
}
else {
x += EditorUtil.charWidth(c, fontType, this);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
index 20c08ec4ec99..032573521b56 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
@@ -42,6 +42,7 @@ import com.intellij.openapi.editor.ex.*;
import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.impl.EditorWindowHolder;
+import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Disposer;
@@ -127,9 +128,10 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
void recalcEditorDimensions() {
EditorImpl.MyScrollBar scrollBar = myEditor.getVerticalScrollBar();
- int scrollBarHeight = scrollBar.getSize().height;
+ int scrollBarHeight = Math.max(0, scrollBar.getSize().height);
myEditorScrollbarTop = scrollBar.getDecScrollButtonHeight()/* + 1*/;
+ assert myEditorScrollbarTop>=0;
int editorScrollbarBottom = scrollBar.getIncScrollButtonHeight();
myEditorTargetHeight = scrollBarHeight - myEditorScrollbarTop - editorScrollbarBottom;
myEditorSourceHeight = myEditor.getPreferredHeight();
@@ -758,20 +760,32 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
Color color,
boolean drawTopDecoration,
boolean drawBottomDecoration) {
+ GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
int x = isMirrored() ? 3 : 5;
int paintWidth = width;
boolean flatStyle = Registry.is("ide.new.markup.markers");
if (thinErrorStripeMark) {
paintWidth /= 2;
- paintWidth += flatStyle ? 0 : 1;
+ paintWidth += flatStyle ? -2 : 1;
x = isMirrored() ? width + 2 : 0;
+ if (yEnd - yStart < 6) {
+ yStart -= 1;
+ yEnd += yEnd-yStart - 1;
+ }
}
if (color == null) return;
- Color darker = UIUtil.isUnderDarcula()? color : ColorUtil.shift(color, 0.75);
+ Color darker = color;
+ if (!UIUtil.isUnderDarcula()) {
+ float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null);
+ hsb[2] = Math.min(1f, hsb[2] * 0.85f);
+ //noinspection UseJBColor
+ darker = new Color(Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]));
+ }
if (flatStyle) {
g.setColor(darker);
- g.fillRect(x, yStart, paintWidth, yEnd - yStart + 1);
+ g.fillRoundRect(x, yStart, paintWidth, yEnd - yStart, 3,3);
+ config.restore();
return;
}
@@ -794,6 +808,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
//right decoration
UIUtil.drawLine(g, x + paintWidth - 2, yStart, x + paintWidth - 2, yEnd/* - 1*/);
+ config.restore();
}
// mouse events
@@ -1056,29 +1071,30 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
int startLineNumber = end == -1 ? 0 : offsetToLine(start, document);
int startY;
int lineCount;
- if (myEditorSourceHeight < myEditorTargetHeight) {
+ int editorTargetHeight = Math.max(0, myEditorTargetHeight);
+ if (myEditorSourceHeight < editorTargetHeight) {
lineCount = 0;
startY = myEditorScrollbarTop + startLineNumber * myEditor.getLineHeight();
}
else {
lineCount = myEditorSourceHeight / myEditor.getLineHeight();
- startY = myEditorScrollbarTop + (int)((float)startLineNumber / lineCount * myEditorTargetHeight);
+ startY = myEditorScrollbarTop + (int)((float)startLineNumber / lineCount * editorTargetHeight);
}
int endY;
int endLineNumber = offsetToLine(end, document);
if (end == -1 || start == -1) {
- endY = Math.min(myEditorSourceHeight, myEditorTargetHeight);
+ endY = Math.min(myEditorSourceHeight, editorTargetHeight);
}
else if (start == end || offsetToLine(start, document) == endLineNumber) {
endY = startY; // both offsets are on the same line, no need to recalc Y position
}
else {
- if (myEditorSourceHeight < myEditorTargetHeight) {
+ if (myEditorSourceHeight < editorTargetHeight) {
endY = myEditorScrollbarTop + endLineNumber * myEditor.getLineHeight();
}
else {
- endY = myEditorScrollbarTop + (int)((float)endLineNumber / lineCount * myEditorTargetHeight);
+ endY = myEditorScrollbarTop + (int)((float)endLineNumber / lineCount * editorTargetHeight);
}
}
if (endY < startY) endY = startY;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
index 3a819d88a370..881dc4100204 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
@@ -270,8 +270,9 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
EditorPosition position = new EditorPosition(logical, start, myEditor);
position.x = point.x;
int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor);
+ int plainSpaceWidth = EditorUtil.getSpaceWidth(Font.PLAIN, myEditor);
- myContext.logicalLineData.update(logical.line, spaceWidth, myEditor);
+ myContext.logicalLineData.update(logical.line, spaceWidth, plainSpaceWidth);
myContext.currentPosition = position;
myContext.lineStartPosition = position.clone();
@@ -363,8 +364,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
revertListeners(softWrap.getStart(), myContext.currentPosition.visualLine);
for (int j = foldRegion.getStartOffset() - 1; j >= softWrap.getStart(); j--) {
int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor];
- int tmpFontType = myOffset2fontType.get(j);
- int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType));
+ int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getPlainSpaceWidth());
myContext.currentPosition.offset--;
myContext.currentPosition.logicalColumn -= columnsDiff;
myContext.currentPosition.visualColumn -= columnsDiff;
@@ -582,8 +582,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
revertListeners(actualSoftWrapOffset, myContext.currentPosition.visualLine);
for (int j = offset - 1; j >= actualSoftWrapOffset; j--) {
int pixelsDiff = myOffset2widthInPixels.data[j - myOffset2widthInPixels.anchor];
- int tmpFontType = myOffset2fontType.get(j);
- int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getSpaceWidth(tmpFontType));
+ int columnsDiff = calculateWidthInColumns(myContext.text.charAt(j), pixelsDiff, myContext.getPlainSpaceWidth());
myContext.currentPosition.offset--;
myContext.currentPosition.logicalColumn -= columnsDiff;
myContext.currentPosition.visualColumn -= columnsDiff;
@@ -630,12 +629,12 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
return Math.max(start, end);
}
- private static int calculateWidthInColumns(char c, int widthInPixels, int spaceWithInPixels) {
+ private static int calculateWidthInColumns(char c, int widthInPixels, int plainSpaceWithInPixels) {
if (c != '\t') {
return 1;
}
- int result = widthInPixels / spaceWithInPixels;
- if (widthInPixels % spaceWithInPixels > 0) {
+ int result = widthInPixels / plainSpaceWithInPixels;
+ if (widthInPixels % plainSpaceWithInPixels > 0) {
result++;
}
return result;
@@ -869,7 +868,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
}
}
updateLastTopLeftCornerOffset();
- return result;
+ return true;
}
private void updateLastTopLeftCornerOffset() {
@@ -1035,7 +1034,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
public int endLineOffset;
public int nonWhiteSpaceSymbolOffset;
- public void update(int logicalLine, int spaceWidth, Editor editor) {
+ public void update(int logicalLine, int spaceWidth, int plainSpaceWidth) {
Document document = myEditor.getDocument();
int startLineOffset;
if (logicalLine >= document.getLineCount()) {
@@ -1055,8 +1054,8 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
switch (c) {
case ' ': indentInColumns += 1; indentInPixels += spaceWidth; break;
case '\t':
- int x = EditorUtil.nextTabStop(indentInPixels, editor);
- indentInColumns += calculateWidthInColumns(c, x - indentInPixels, spaceWidth);
+ int x = EditorUtil.nextTabStop(indentInPixels, myEditor);
+ indentInColumns += calculateWidthInColumns(c, x - indentInPixels, plainSpaceWidth);
indentInPixels = x;
break;
default: nonWhiteSpaceSymbolOffset = i; return;
@@ -1270,8 +1269,12 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
public int getSpaceWidth() {
return getSpaceWidth(fontType);
}
-
- public int getSpaceWidth(@JdkConstants.FontStyle int fontType) {
+
+ public int getPlainSpaceWidth() {
+ return getSpaceWidth(Font.PLAIN);
+ }
+
+ private int getSpaceWidth(@JdkConstants.FontStyle int fontType) {
int result = fontType2spaceWidth.get(fontType);
if (result <= 0) {
result = EditorUtil.getSpaceWidth(fontType, myEditor);
@@ -1280,7 +1283,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
assert result > 0;
return result;
}
-
+
/**
* Asks current context to update its state assuming that it begins to point to the line next to its current position.
*/
@@ -1293,7 +1296,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
lastFoldEndPosition = null;
lastFold = null;
lineStartPosition.from(currentPosition);
- logicalLineData.update(currentPosition.logicalLine, getSpaceWidth(), myEditor);
+ logicalLineData.update(currentPosition.logicalLine, getSpaceWidth(), getPlainSpaceWidth());
fontType = myOffset2fontType.get(currentPosition.offset);
myOffset2fontType.clear();
@@ -1330,7 +1333,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
myOffset2widthInPixels.data[currentPosition.offset - myOffset2widthInPixels.anchor] = widthInPixels;
myOffset2widthInPixels.end++;
- int widthInColumns = calculateWidthInColumns(c, widthInPixels, myContext.getSpaceWidth());
+ int widthInColumns = calculateWidthInColumns(c, widthInPixels, myContext.getPlainSpaceWidth());
if (c == '\t') {
notifyListenersOnVisualLineStart(myContext.lineStartPosition);
notifyListenersOnTabulation(widthInColumns);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java
index 92ef12c46558..48ba57e150cf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java
@@ -151,6 +151,12 @@ public class TextComponentCaret extends UserDataHolderBase implements Caret {
}
@Override
+ public void setSelection(int startOffset, int endOffset, boolean updateSystemSelection) {
+ // updating system selection is not supported currently for TextComponentEditor
+ setSelection(startOffset, endOffset);
+ }
+
+ @Override
public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
getSelectionModel().setSelection(startOffset, endPosition, endOffset);
}
@@ -161,6 +167,13 @@ public class TextComponentCaret extends UserDataHolderBase implements Caret {
}
@Override
+ public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset,
+ boolean updateSystemSelection) {
+ // updating system selection is not supported currently for TextComponentEditor
+ setSelection(startPosition, startOffset, endPosition, endOffset);
+ }
+
+ @Override
public void removeSelection() {
getSelectionModel().removeSelection();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
index ac415f5f9409..341c8ace3598 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaretModel.java
@@ -187,6 +187,11 @@ public class TextComponentCaretModel implements CaretModel {
throw new UnsupportedOperationException("Multiple carets are not supported");
}
+ @Override
+ public void setCaretsAndSelections(@NotNull List<CaretState> caretStates, boolean updateSystemSelection) {
+ throw new UnsupportedOperationException("Multiple carets are not supported");
+ }
+
@NotNull
@Override
public List<CaretState> getCaretsAndSelections() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
index b1f9ec0c2b93..b9e38809faab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
@@ -148,7 +148,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
}
- private boolean showEmptyText() {
+ protected boolean showEmptyText() {
return myCurrentWindow == null || myCurrentWindow.getFiles().length == 0;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
index cce6de27545d..ec2559fc06ba 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
@@ -550,14 +550,18 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt
if (document != null) {
// a file is linked to a document - chances are it is an "unknown text file" now
if (isBinaryWithoutDecompiler(file)) {
- myDocuments.remove(file);
- file.putUserData(HARD_REF_TO_DOCUMENT_KEY, null);
- document.putUserData(FILE_KEY, null);
+ unbindFileFromDocument(file, document);
}
}
}
}
+ private void unbindFileFromDocument(@NotNull VirtualFile file, @NotNull Document document) {
+ myDocuments.remove(file);
+ file.putUserData(HARD_REF_TO_DOCUMENT_KEY, null);
+ document.putUserData(FILE_KEY, null);
+ }
+
private static boolean isBinaryWithDecompiler(@NotNull VirtualFile file) {
final FileType ft = file.getFileType();
return ft.isBinary() && BinaryFileTypeDecompilers.INSTANCE.forFileType(ft) != null;
@@ -609,6 +613,13 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt
return;
}
+ if (file.getLength() > FileUtilRt.LARGE_FOR_CONTENT_LOADING) {
+ unbindFileFromDocument(file, document);
+ myUnsavedDocuments.remove(document);
+ myMultiCaster.fileWithNoDocumentChanged(file);
+ return;
+ }
+
final Project project = ProjectLocator.getInstance().guessProjectForFile(file);
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
@@ -640,7 +651,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt
public boolean process(final VirtualFile file, final Document document) {
String message = UIBundle.message("file.cache.conflict.message.text", file.getPresentableUrl());
- final DialogBuilder builder = new DialogBuilder((Project)null);
+ final DialogBuilder builder = new DialogBuilder();
builder.setCenterPanel(new JLabel(message, Messages.getQuestionIcon(), SwingConstants.CENTER));
builder.addOkAction().setText(UIBundle.message("file.cache.conflict.load.fs.changes.button"));
builder.addCancelAction().setText(UIBundle.message("file.cache.conflict.keep.memory.changes.button"));
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index bab6d2b2fa4f..65adf52041b9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -58,6 +58,7 @@ import com.intellij.openapi.vcs.FileStatusListener;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
@@ -90,6 +91,7 @@ import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Anton Katilin
@@ -106,10 +108,12 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
public static final String FILE_EDITOR_MANAGER = "FileEditorManager";
private volatile JPanel myPanels;
+ private PreviewPanel myPreviewPanel;
private EditorsSplitters mySplitters;
private final Project myProject;
private final List<Pair<VirtualFile, EditorWindow>> mySelectionHistory = new ArrayList<Pair<VirtualFile, EditorWindow>>();
private WeakReference<EditorComposite> myLastSelectedComposite = new WeakReference<EditorComposite>(null);
+ private final AtomicBoolean myPreviewBlocker = new AtomicBoolean(false);
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null);
@@ -174,7 +178,11 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
public Set<EditorsSplitters> getAllSplitters() {
- HashSet<EditorsSplitters> all = new HashSet<EditorsSplitters>();
+ HashSet<EditorsSplitters> all = new LinkedHashSet<EditorsSplitters>();
+ if (Registry.is("editor.use.preview")) {
+ initUI();
+ all.add(myPreviewPanel.getWindow().getOwner());
+ }
all.add(getMainSplitters());
Set<DockContainer> dockContainers = myDockManager.getContainers();
for (DockContainer each : dockContainers) {
@@ -247,6 +255,11 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
}
}
+ if (myPreviewPanel == null && Registry.is("editor.use.preview")) {
+ synchronized (myInitLock) {
+ myPreviewPanel = new PreviewPanel(myProject, this, myDockManager);
+ }
+ }
}
private static class MyBorder implements Border {
@@ -595,7 +608,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
@NotNull
public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull final VirtualFile file,
final boolean focusEditor,
- boolean searchForSplitter) {
+ final boolean searchForSplitter) {
if (!file.isValid()) {
throw new IllegalArgumentException("file is not valid: " + file);
}
@@ -628,6 +641,13 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
wndToOpenIn = getSplitters().getCurrentWindow();
}
+ if (wndToOpenIn == null || !wndToOpenIn.isFileOpen(file)) {
+ EditorWindow previewWindow = getPreviewWindow(file, focusEditor, searchForSplitter);
+ if (previewWindow != null) {
+ wndToOpenIn = previewWindow;
+ }
+ }
+
EditorsSplitters splitters = getSplitters();
if (wndToOpenIn == null) {
@@ -638,6 +658,31 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
return openFileImpl2(wndToOpenIn, file, focusEditor);
}
+ @Nullable
+ private EditorWindow getPreviewWindow(@NotNull VirtualFile virtualFile, final boolean focusEditor, final boolean searchForSplitter) {
+ EditorWindow wndToOpenIn = null;
+ if (Registry.is("editor.use.preview") && !myPreviewBlocker.get()) {
+ wndToOpenIn = myPreviewPanel.getWindow();
+ if (virtualFile.equals(myPreviewPanel.getCurrentFile())) return wndToOpenIn;
+ final VirtualFile modifiedFile = myPreviewPanel.closeCurrentFile();
+ ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).activate(null, false);
+ if (modifiedFile != null) {
+ CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+ @Override
+ public void run() {
+ myPreviewBlocker.set(true);
+ try {
+ openFileWithProviders(modifiedFile, focusEditor, searchForSplitter);
+ } finally {
+ myPreviewBlocker.set(false);
+ }
+ }
+ }, "", null);
+ }
+ }
+ return wndToOpenIn;
+ }
+
public Pair<FileEditor[], FileEditorProvider[]> openFileInNewWindow(@NotNull VirtualFile file) {
return ((DockManagerImpl)DockManager.getInstance(getProject())).createNewDockContainerFor(file, this);
}
@@ -1610,7 +1655,10 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
return null;
}
- public void runChange(FileEditorManagerChange change, EditorsSplitters splitters) {
+ /**
+ * @param splitters - taken getAllSplitters() value if parameter is null
+ */
+ public void runChange(@NotNull FileEditorManagerChange change, @Nullable EditorsSplitters splitters) {
Set<EditorsSplitters> target = new HashSet<EditorsSplitters>();
if (splitters == null) {
target.addAll(getAllSplitters());
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java
new file mode 100644
index 000000000000..a9634d5a335a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.fileEditor.impl;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.ui.UISettings;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.event.DocumentListener;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerListener;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowId;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.impl.ToolWindowImpl;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.docking.DockManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+
+class PreviewPanel extends JPanel implements DocumentListener, FileEditorManagerListener.Before {
+ private static final int HISTORY_LIMIT = 10;
+
+ private final Project myProject;
+ private final FileEditorManagerImpl myManager;
+ private final DockManager myDockManager;
+ private EditorWindow myWindow;
+ private boolean myInitialized = false;
+ private EditorsSplitters myEditorsSplitters;
+ private ArrayList<VirtualFile> myHistory = new ArrayList<VirtualFile>();
+ private VirtualFile myModifiedFile = null;
+ private ToolWindowImpl myToolWindow;
+ private VirtualFile myAwaitingForOpen = null;
+
+ public PreviewPanel(Project project, FileEditorManagerImpl manager, DockManager dockManager) {
+ myProject = project;
+ myManager = manager;
+ myDockManager = dockManager;
+ setOpaque(true);
+ setBackground(JBColor.DARK_GRAY);
+ }
+
+ private void initToolWindowIfNeed() {
+ if (myInitialized) return;
+
+ myToolWindow = (ToolWindowImpl)ToolWindowManager.getInstance(myProject)
+ .registerToolWindow(ToolWindowId.PREVIEW, this, ToolWindowAnchor.RIGHT, myProject, false);
+ myToolWindow.setIcon(AllIcons.Actions.PreviewDetails);
+
+ myEditorsSplitters = new EditorsSplitters(myManager, myDockManager, false) {
+ @Override
+ public void updateFileName(VirtualFile updatedFile) {
+ super.updateFileName(updatedFile);
+ if (updatedFile != null && updatedFile.equals(getCurrentFile())) {
+ updateWindowTitle(updatedFile);
+ }
+ }
+
+ @Override
+ protected void afterFileOpen(VirtualFile file) {
+ if (file.equals(myAwaitingForOpen)) {
+ updateWindowTitle(file);
+ Document document = FileDocumentManager.getInstance().getDocument(file);
+ if (document != null) {
+ myModifiedFile = null;
+ document.addDocumentListener(PreviewPanel.this, myProject);
+ }
+ }
+ myAwaitingForOpen = null;
+ }
+
+ @Override
+ public void setTabsPlacement(int tabPlacement) {
+ super.setTabsPlacement(UISettings.TABS_NONE);
+ }
+
+ @Override
+ protected boolean showEmptyText() {
+ return false;
+ }
+ };
+
+ myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER, this);
+ myEditorsSplitters.createCurrentWindow();
+
+ myWindow = myEditorsSplitters.getCurrentWindow();
+ myWindow.setTabsPlacement(UISettings.TABS_NONE);
+
+ setLayout(new GridLayout(1, 1));
+ add(myEditorsSplitters);
+
+ myToolWindow.setTitleActions(new MoveToEditorTabsAction(), new CloseFileAction());
+
+ myInitialized = true;
+ }
+
+ private void updateWindowTitle(VirtualFile file) {
+ if (myToolWindow == null) return;
+ if (file == null) {
+ myToolWindow.setTitle(": (empty)");
+ }
+ else {
+ myToolWindow.setTitle(": " +
+ StringUtil.getShortened(EditorTabbedContainer.calcTabTitle(myProject, file),
+ UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT));
+ }
+ }
+
+ @Override
+ public void beforeFileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ myAwaitingForOpen = file;
+ }
+
+ @Override
+ public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ if (file.equals(getCurrentFile())) {
+ updateWindowTitle(null);
+ Document document = FileDocumentManager.getInstance().getDocument(file);
+ if (document != null) {
+ document.removeDocumentListener(this);
+ }
+ }
+ }
+
+
+ @Override
+ public void beforeDocumentChange(DocumentEvent event) {
+
+ }
+
+ @Override
+ public void documentChanged(DocumentEvent event) {
+ VirtualFile file = FileDocumentManager.getInstance().getFile(event.getDocument());
+ if (file != null) {
+ myModifiedFile = file;
+ }
+ }
+
+ EditorWindow getWindow() {
+ initToolWindowIfNeed();
+ return myWindow;
+ }
+
+ @Nullable
+ VirtualFile getCurrentFile() {
+ VirtualFile[] files = myWindow.getFiles();
+ return files.length == 1 ? files[0] : null;
+ }
+
+ private class MoveToEditorTabsAction extends AnAction {
+ public MoveToEditorTabsAction() {
+ super(null, "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ VirtualFile virtualFile = getCurrentFile();
+ if (virtualFile == null) {
+ return;
+ }
+
+ myManager.openFileWithProviders(virtualFile, false, myManager.getCurrentWindow());
+ closeCurrentFile();
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ VirtualFile currentFile = getCurrentFile();
+ e.getPresentation().setEnabled(currentFile != null);
+ if (currentFile == null) return;
+
+ if (isModified(currentFile)) {
+ e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeft);
+ }
+ else {
+ e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeftGrayed);
+ }
+ }
+ }
+
+ private boolean isModified(@NotNull VirtualFile file) {
+ return file.equals(myModifiedFile);
+ }
+
+ //returns last open file if it has "modified" status
+ @Nullable
+ VirtualFile closeCurrentFile() {
+ VirtualFile virtualFile = getCurrentFile();
+ if (virtualFile == null) return null;
+ if (!myHistory.contains(virtualFile)) {
+ myHistory.add(virtualFile);
+ while (myHistory.size() > HISTORY_LIMIT) {
+ myHistory.remove(0);
+ }
+ }
+ myWindow.closeFile(virtualFile);
+ this.revalidate();
+ this.repaint();
+ return isModified(virtualFile) ? virtualFile : null;
+ }
+
+ private class CloseFileAction extends AnAction {
+ public CloseFileAction() {
+ super(null, "Close", AllIcons.Actions.Close);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ if (getCurrentFile() == null) return;
+ closeCurrentFile();
+ ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).hide(null);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ e.getPresentation().setEnabled(getCurrentFile() != null);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
index b24927b70726..076d29e64bbe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -32,7 +32,7 @@ import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
import com.intellij.openapi.vfs.impl.http.RemoteFileInfo;
import com.intellij.openapi.vfs.impl.http.RemoteFileState;
import com.intellij.ui.AppUIUtil;
-import com.intellij.util.net.HTTPProxySettingsDialog;
+import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
@@ -86,22 +86,22 @@ public class RemoteFilePanel {
remoteFileInfo.addDownloadingListener(myDownloadingListener);
myCancelButton.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(final ActionEvent e) {
+ public void actionPerformed(@NotNull final ActionEvent e) {
remoteFileInfo.cancelDownloading();
}
});
myTryAgainButton.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(final ActionEvent e) {
+ public void actionPerformed(@NotNull final ActionEvent e) {
showCard(DOWNLOADING_CARD);
remoteFileInfo.restartDownloading();
}
});
myChangeProxySettingsButton.addActionListener(new ActionListener() {
@Override
- public void actionPerformed(final ActionEvent e) {
- new HTTPProxySettingsDialog().show();
+ public void actionPerformed(@NotNull ActionEvent e) {
+ HttpConfigurable.editConfigurable(myMainPanel);
}
});
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
index 690e7c7d2820..14f0c95ec31b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
@@ -287,7 +287,7 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware {
new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
}
- caretModel.setCaretsAndSelections(states);
+ caretModel.setCaretsAndSelections(states, false);
}
else {
LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
index 198ed907a8d9..837626b53246 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.TransferToPooledThreadQueue;
import com.intellij.openapi.components.ExportableApplicationComponent;
import com.intellij.openapi.components.RoamingType;
+import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
@@ -120,7 +121,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
private static final String[] FILE_TYPES_WITH_PREDEFINED_EXTENSIONS = {"JSP", "JSPX", "DTD", "HTML", "Properties", "XHTML"};
private final SchemesManager<FileType, AbstractFileType> mySchemesManager;
@NonNls
- private static final String FILE_SPEC = "$ROOT_CONFIG$/filetypes";
+ private static final String FILE_SPEC = StoragePathMacros.ROOT_CONFIG + "/filetypes";
private final ConcurrentBitSet autoDetectWasRun = new ConcurrentBitSet();
private final ConcurrentBitSet autoDetectedAsText = new ConcurrentBitSet();
private final ConcurrentBitSet autoDetectedAsBinary = new ConcurrentBitSet();
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
index 7c65a805ee6c..7c30e4faedec 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
@@ -67,7 +67,7 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat
KeymapManagerImpl(DefaultKeymap defaultKeymap, SchemesManagerFactory factory) {
mySchemesManager = factory.createSchemesManager(
- "$ROOT_CONFIG$/keymaps",
+ StoragePathMacros.ROOT_CONFIG + "/keymaps",
new BaseSchemeProcessor<KeymapImpl>() {
@Override
public KeymapImpl readScheme(@NotNull final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/CompositeConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/CompositeConfigurable.java
index 0b9e5ade8d29..aaba0fdbaf6b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/CompositeConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/CompositeConfigurable.java
@@ -20,18 +20,21 @@ import java.util.List;
public abstract class CompositeConfigurable<T extends UnnamedConfigurable> extends BaseConfigurable {
private List<T> myConfigurables;
+ @Override
public void reset() {
for (T configurable : getConfigurables()) {
configurable.reset();
}
}
+ @Override
public void apply() throws ConfigurationException {
for (T configurable : getConfigurables()) {
configurable.apply();
}
}
+ @Override
public boolean isModified() {
for (T configurable : getConfigurables()) {
if (configurable.isModified()) {
@@ -41,6 +44,7 @@ public abstract class CompositeConfigurable<T extends UnnamedConfigurable> exten
return false;
}
+ @Override
public void disposeUIResources() {
if (myConfigurables != null) {
for (final T myConfigurable : myConfigurables) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
deleted file mode 100644
index d7c7dca2f19b..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2000-2014 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options;
-
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implements SearchableConfigurable, Configurable.NoScroll {
- private final String id;
- private final String displayName;
- private final String helpTopic;
-
- private UI ui;
-
- protected ConfigurableBase(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic) {
- this.id = id;
- this.displayName = displayName;
- this.helpTopic = helpTopic;
- }
-
- @NotNull
- @Override
- public final String getId() {
- return id;
- }
-
- @Nls
- @Override
- public final String getDisplayName() {
- return displayName;
- }
-
- @Nullable
- @Override
- public final String getHelpTopic() {
- return helpTopic;
- }
-
- @Nullable
- @Override
- public Runnable enableSearch(String option) {
- return null;
- }
-
- @NotNull
- protected abstract S getSettings();
-
- @Override
- public void reset() {
- if (ui != null) {
- ui.reset(getSettings());
- }
- }
-
- @Nullable
- @Override
- public final JComponent createComponent() {
- if (ui == null) {
- ui = createUi();
- }
- return ui.getComponent();
- }
-
- protected abstract UI createUi();
-
- @Override
- public final boolean isModified() {
- return ui != null && ui.isModified(getSettings());
- }
-
- @Override
- public final void apply() {
- if (ui != null) {
- ui.apply(getSettings());
- }
- }
-
- @Override
- public void disposeUIResources() {
- ui = null;
- }
-} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
deleted file mode 100644
index 0ecb19a7ce8e..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2000-2014 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options;
-
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-public interface ConfigurableUi<S> {
- void reset(@NotNull S settings);
-
- boolean isModified(@NotNull S settings);
-
- void apply(@NotNull S settings);
-
- @NotNull
- JComponent getComponent();
-} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
index 323394ad7c94..449a2180e3c1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.ServiceBean;
import com.intellij.openapi.components.SettingsSavingComponent;
+import com.intellij.openapi.components.impl.stores.IApplicationStore;
import com.intellij.openapi.components.impl.stores.StreamProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.containers.ContainerUtil;
@@ -32,21 +33,22 @@ import java.util.Collections;
import java.util.List;
public class SchemesManagerFactoryImpl extends SchemesManagerFactory implements SettingsSavingComponent {
-
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.options.SchemesManagerFactoryImpl");
+ private static final Logger LOG = Logger.getInstance(SchemesManagerFactoryImpl.class);
private final List<SchemesManagerImpl> myRegisteredManagers = ContainerUtil.createLockFreeCopyOnWriteList();
@Override
- public <T extends Scheme, E extends ExternalizableScheme> SchemesManager<T, E> createSchemesManager(final String fileSpec,
- final SchemeProcessor<E> processor,
- final RoamingType roamingType) {
+ public <T extends Scheme, E extends ExternalizableScheme> SchemesManager<T, E> createSchemesManager(@NotNull String fileSpec,
+ @NotNull SchemeProcessor<E> processor,
+ @NotNull RoamingType roamingType) {
final Application application = ApplicationManager.getApplication();
- if (!(application instanceof ApplicationImpl)) return null;
- String baseDirPath = ((ApplicationImpl)application).getStateStore().getStateStorageManager().expandMacros(fileSpec);
-
+ if (!(application instanceof ApplicationImpl)) {
+ return null;
+ }
+ IApplicationStore applicationStore = ((ApplicationImpl)application).getStateStore();
+ String baseDirPath = applicationStore.getStateStorageManager().expandMacros(fileSpec);
if (baseDirPath != null) {
- StreamProvider provider = ((ApplicationImpl)ApplicationManager.getApplication()).getStateStore().getStateStorageManager().getStreamProvider();
+ StreamProvider provider = applicationStore.getStateStorageManager().getStreamProvider();
SchemesManagerImpl<T, E> manager = new SchemesManagerImpl<T, E>(fileSpec, processor, roamingType, provider, new File(baseDirPath));
myRegisteredManagers.add(manager);
return manager;
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
index 1c7e768c7d83..4ff3ebba1ee9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFileAdapter;
import com.intellij.openapi.vfs.VirtualFileEvent;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.Alarm;
+import com.intellij.util.SmartList;
import com.intellij.util.UniqueFileNamesProvider;
import com.intellij.util.containers.HashSet;
import com.intellij.util.text.UniqueNameGenerator;
@@ -51,7 +52,7 @@ import java.io.IOException;
import java.util.*;
public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme> extends AbstractSchemesManager<T, E> {
- private static final Logger LOG = Logger.getInstance("#" + SchemesManagerFactoryImpl.class.getName());
+ private static final Logger LOG = Logger.getInstance(SchemesManagerFactoryImpl.class);
@NonNls private static final String DEFAULT_EXT = ".xml";
@@ -292,12 +293,13 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
+ @NotNull
private Collection<E> readSchemesFromProviders() {
- Collection<E> result = new ArrayList<E>();
if (myProvider == null || !myProvider.isEnabled()) {
- return result;
+ return Collections.emptyList();
}
+ Collection<E> result = new SmartList<E>();
for (String subPath : myProvider.listSubFiles(myFileSpec, myRoamingType)) {
if (!subPath.equals(DELETED_XML)) {
try {
@@ -305,6 +307,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
if (subDocument != null) {
E scheme = readScheme(subDocument);
boolean fileRenamed = false;
+ assert scheme != null;
T existing = findSchemeByName(scheme.getName());
if (existing != null && existing instanceof ExternalizableScheme) {
String currentFileName = ((ExternalizableScheme)existing).getExternalInfo().getCurrentFileName();
@@ -315,7 +318,6 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
String fileName = checkFileNameIsFree(subPath, scheme.getName());
-
if (!fileRenamed && !fileName.equals(subPath)) {
deleteServerFiles(subPath);
}
@@ -325,7 +327,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
catch (Exception e) {
- LOG.info("Cannot load data from IDEAServer: " + e.getLocalizedMessage());
+ LOG.info("Cannot load data from stream provider: " + e.getLocalizedMessage());
}
}
}
@@ -347,21 +349,22 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
});
}
- private String checkFileNameIsFree(final String subPath, final String schemeName) {
+ @NotNull
+ private String checkFileNameIsFree(@NotNull String subPath, @NotNull String schemeName) {
for (Scheme scheme : mySchemes) {
if (scheme instanceof ExternalizableScheme) {
- ExternalInfo externalInfo = ((ExternalizableScheme)scheme).getExternalInfo();
- String name = externalInfo.getCurrentFileName();
- if (name != null) {
- String fileName = name + mySchemeExtension;
- if (fileName.equals(subPath) && !Comparing.equal(schemeName, scheme.getName())) {
- return createUniqueFileName(collectAllFileNames(), UniqueFileNamesProvider.convertName(schemeName));
+ String name = ((ExternalizableScheme)scheme).getExternalInfo().getCurrentFileName();
+ if (name != null &&
+ !schemeName.equals(scheme.getName()) &&
+ subPath.length() == (name.length() + mySchemeExtension.length()) &&
+ subPath.startsWith(name) &&
+ subPath.endsWith(mySchemeExtension)) {
+ return UniqueNameGenerator.generateUniqueName(UniqueFileNamesProvider.convertName(schemeName), collectAllFileNames());
/*VirtualFile oldFile = myVFSBaseDir.findChild(subPath);
if (oldFile != null) {
oldFile.copy(this, myVFSBaseDir, uniqueFileName + EXT);
}
externalInfo.setCurrentFileName(uniqueFileName);*/
- }
}
}
}
@@ -369,8 +372,9 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return subPath;
}
+ @NotNull
private Collection<String> collectAllFileNames() {
- HashSet<String> result = new HashSet<String>();
+ Set<String> result = new THashSet<String>();
for (T scheme : mySchemes) {
if (scheme instanceof ExternalizableScheme) {
ExternalInfo externalInfo = ((ExternalizableScheme)scheme).getExternalInfo();
@@ -382,10 +386,6 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return result;
}
- private static String createUniqueFileName(final Collection<String> strings, final String schemeName) {
- return UniqueNameGenerator.generateUniqueName(schemeName, strings);
- }
-
private void loadScheme(final E scheme, boolean forceAdd, final String name) {
if (scheme != null && (!myDeletedNames.contains(scheme.getName()) || forceAdd)) {
T existing = findSchemeByName(scheme.getName());
@@ -469,13 +469,6 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
final E scheme = readScheme(document);
if (scheme != null) {
- if (scheme.getName() == null) {
- String suggestedName = FileUtil.getNameWithoutExtension(file.getName());
- if (!"_".equals(suggestedName)) {
- scheme.setName(suggestedName);
- }
- }
-
loadScheme(scheme, forceAdd, file.getName());
result.add(scheme);
}
@@ -653,8 +646,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
result = new SharedSchemeData(original, name, user, description);
}
else {
- Document original = subDocument;
- result = new SharedSchemeData(original, name, null, null);
+ result = new SharedSchemeData(subDocument, name, null, null);
}
return result;
}
@@ -673,8 +665,8 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return false;
}
- private String getFileFullPath(final String subPath) {
- return myFileSpec + "/" + subPath;
+ private String getFileFullPath(@NotNull String subPath) {
+ return myFileSpec + '/' + subPath;
}
@Override
@@ -843,9 +835,9 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
deleteServerFiles(fileName);
}
- private void deleteServerFiles(final String fileName) {
+ private void deleteServerFiles(@NotNull String path) {
if (myProvider != null && myProvider.isEnabled()) {
- StorageUtil.deleteContent(myProvider, getFileFullPath(fileName), myRoamingType);
+ StorageUtil.delete(myProvider, getFileFullPath(path), myRoamingType);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
deleted file mode 100644
index 9812165932a2..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2000-2014 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options;
-
-import com.intellij.openapi.util.Getter;
-import com.intellij.util.ReflectionUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public final class SimpleConfigurable<UI extends ConfigurableUi<S>, S> extends ConfigurableBase<UI, S> {
- private final Class<UI> uiClass;
- private final Getter<S> settingsGetter;
-
- private SimpleConfigurable(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
- super(id, displayName, helpTopic);
-
- this.uiClass = uiClass;
- this.settingsGetter = settingsGetter;
- }
-
- public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
- return new SimpleConfigurable<UI, S>(id, displayName, helpTopic, uiClass, settingsGetter);
- }
-
- public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
- return create(id, displayName, id, uiClass, settingsGetter);
- }
-
- @NotNull
- @Override
- protected S getSettings() {
- return settingsGetter.get();
- }
-
- @Override
- protected UI createUi() {
- return ReflectionUtil.newInstance(uiClass);
- }
-} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
index 5f8dc0e890df..3b67a3478368 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
@@ -165,10 +165,6 @@ public class ConfigurableWrapper implements SearchableConfigurable {
return myEp;
}
- public String getGroupId() {
- return myEp.groupId;
- }
-
public String getParentId() {
return myEp.parentId;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java
index 96cc9e451185..c80a222ffd96 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/GlassPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -17,7 +17,10 @@
package com.intellij.openapi.options.ex;
import com.intellij.ide.ui.search.SearchUtil;
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.ColorUtil;
import com.intellij.ui.components.JBTabbedPane;
+import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +30,7 @@ import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.Kernel;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -64,17 +68,19 @@ public class GlassPanel extends JComponent {
final Point leftPoint = SwingUtilities.convertPoint(myPanel, new Point(visibleRect.x, visibleRect.y), surfaceComponent);
Area innerPanel = new Area(new Rectangle2D.Double(leftPoint.x, leftPoint.y, visibleRect.width, visibleRect.height));
Area mask = new Area(screen);
-
+ ArrayList<JComponent> components = new ArrayList<JComponent>();
for (JComponent lightComponent : myLightComponents) {
- final Area area = getComponentArea(surfaceComponent, lightComponent);
+ final Area area = getComponentArea(surfaceComponent, lightComponent, 1);
if (area == null) continue;
+ components.add(lightComponent);
if (lightComponent instanceof JLabel) {
final JLabel label = (JLabel)lightComponent;
final Component labelFor = label.getLabelFor();
if (labelFor instanceof JComponent) {
- final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor);
+ final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor, 1);
if (labelForArea != null) {
+ components.add((JComponent)labelFor);
area.add(labelForArea);
}
}
@@ -86,19 +92,32 @@ public class GlassPanel extends JComponent {
Graphics2D g2 = (Graphics2D)g;
- Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.15f);
+ Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.20f);
Color boundsColor = Color.gray;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(shieldColor);
g2.fill(mask);
- g2.setColor(boundsColor);
- g2.draw(mask);
+ g2.setColor(ColorUtil.toAlpha(Color.orange, 25));
+ GraphicsConfig config = GraphicsUtil.setupAAPainting(g2);
+ for (int i = 2; i > 0; i--) {
+ g2.setStroke(new BasicStroke(i));
+ Area arrr = new Area();
+ for (JComponent component : components) {
+ Area area = getComponentArea(surfaceComponent, component, i-1);
+ if (area != null) {
+ arrr.add(area);
+ }
+ }
+ g2.draw(arrr);
+ }
+
+ config.restore();
}
}
@Nullable
- private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent) {
+ private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) {
if (!lightComponent.isShowing()) return null;
final Point panelPoint = SwingUtilities.convertPoint(lightComponent, new Point(0, 0), surfaceComponent);
@@ -115,12 +134,17 @@ public class GlassPanel extends JComponent {
int hInset = isWithBorder ? 7 : isLabelFromTabbedPane ? 20 : 7;
int vInset = isWithBorder ? 1 : isLabelFromTabbedPane ? 10 : 5;
- final Area area = new Area(new RoundRectangle2D.Double(x - hInset + insetsToIgnore.left,
- y - vInset + insetsToIgnore.top,
- lightComponent.getWidth() + hInset * 2 - insetsToIgnore.right - insetsToIgnore.left,
- lightComponent.getHeight() + vInset * 2 - insetsToIgnore.top - insetsToIgnore.bottom,
- 6, 6));
- return area;
+ hInset += offset;
+ vInset += offset;
+ int xCoord = x - hInset + insetsToIgnore.left;
+ int yCoord = y - vInset + insetsToIgnore.top;
+ int width = lightComponent.getWidth() + hInset * 2 - insetsToIgnore.right - insetsToIgnore.left;
+ int height = lightComponent.getHeight() + vInset * 2 - insetsToIgnore.top - insetsToIgnore.bottom;
+ return new Area(new RoundRectangle2D.Double(xCoord,
+ yCoord,
+ width,
+ height,
+ Math.min(height, 30), Math.min(height, 30)));
}
protected static Kernel getBlurKernel(int blurSize) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
index f1411cf3551d..e3404ec017cd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
@@ -17,15 +17,21 @@ package com.intellij.openapi.options.ex;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurableGroup;
+import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
+import javax.swing.JComponent;
-public final class MixedConfigurableGroup implements ConfigurableGroup {
+public final class MixedConfigurableGroup implements SearchableConfigurable, ConfigurableGroup {
private final String myGroupId;
private Configurable[] myConfigurables;
@@ -34,6 +40,7 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
myConfigurables = (configurables != null)
? configurables.toArray(new Configurable[configurables.size()])
: new Configurable[0];
+ Arrays.sort(myConfigurables, COMPARATOR);
}
private MixedConfigurableGroup(String groupId, HashMap<String, ArrayList<Configurable>> configurables) {
@@ -41,6 +48,45 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
}
@Override
+ public JComponent createComponent() {
+ return null;
+ }
+
+ @Override
+ public boolean isModified() {
+ return false;
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void disposeUIResources() {
+ myConfigurables = null;
+ }
+
+ @Override
+ public Runnable enableSearch(String option) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return "configurable.group." + myGroupId;
+ }
+
+ @Override
+ public String getHelpTopic() {
+ return "configurable.group." + myGroupId + ".help.topic";
+ }
+
+ @Override
public String getDisplayName() {
return OptionsBundle.message("configurable.group." + myGroupId + ".settings.display.name");
}
@@ -60,7 +106,7 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
for (Configurable configurable : configurables) {
String groupId = null;
if (configurable instanceof ConfigurableWrapper) {
- groupId = ((ConfigurableWrapper)configurable).getGroupId();
+ groupId = ((ConfigurableWrapper)configurable).getExtensionPoint().groupId;
}
ArrayList<Configurable> list = map.get(groupId);
if (list == null) {
@@ -70,7 +116,7 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
}
ArrayList<Configurable> buildList = map.get("build");
if (buildList != null) {
- NodeConfigurable buildTools = new NodeConfigurable("build.tools");
+ NodeConfigurable buildTools = new NodeConfigurable("build.tools", 1000);
buildTools.add(find("MavenSettings", buildList.iterator()));
buildTools.add(find("reference.settingsdialog.project.gradle", buildList.iterator()));
buildTools.add(find("reference.settingsdialog.project.gant", buildList.iterator()));
@@ -106,4 +152,27 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
}
return null;
}
+
+ public static int getGroupWeight(Configurable configurable) {
+ if (configurable instanceof NodeConfigurable) {
+ return ((NodeConfigurable)configurable).getGroupWeight();
+ }
+ if (configurable instanceof ConfigurableWrapper) {
+ return ((ConfigurableWrapper)configurable).getExtensionPoint().groupWeight;
+ }
+ return 0;
+ }
+
+ private static final Comparator<Configurable> COMPARATOR = new Comparator<Configurable>() {
+ @Override
+ public int compare(Configurable configurable1, Configurable configurable2) {
+ if (configurable1 == null || configurable2 == null) {
+ return configurable2 != null ? -1 : configurable1 != null ? 1 : 0;
+ }
+ int weight1 = getGroupWeight(configurable1);
+ int weight2 = getGroupWeight(configurable2);
+ return weight1 > weight2 ? -1 : weight1 < weight2 ? 1 : StringUtil.naturalCompare(configurable1.getDisplayName(),
+ configurable2.getDisplayName());
+ }
+ };
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
index 6571c7a63746..609943d02943 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
@@ -27,9 +27,15 @@ import java.util.ArrayList;
public final class NodeConfigurable extends SearchableConfigurable.Parent.Abstract {
private final ArrayList<Configurable> myConfigurables = new ArrayList<Configurable>();
private final String myId;
+ private final int myWeight;
- public NodeConfigurable(@NotNull String id) {
+ public NodeConfigurable(@NotNull String id, int weight) {
myId = id;
+ myWeight = weight;
+ }
+
+ public int getGroupWeight() {
+ return myWeight;
}
public void add(Configurable configurable) {
@@ -48,13 +54,13 @@ public final class NodeConfigurable extends SearchableConfigurable.Parent.Abstra
@NotNull
@Override
public String getId() {
- return myId;
+ return "node.configurable." + myId;
}
@Nullable
@Override
public String getHelpTopic() {
- return myId;
+ return "node.configurable." + myId + ".help.topic";
}
@Nls
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java
index 80144d230eaf..def0dd16a2d2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/SingleConfigurableEditor.java
@@ -46,7 +46,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
private Component myParentComponent;
private Configurable myConfigurable;
private JComponent myCenterPanel;
- private String myDimensionKey;
+ private final String myDimensionKey;
private final boolean myShowApplyButton;
private boolean myChangesWereApplied;
@@ -134,6 +134,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
return displayName.replaceAll("\n", " ");
}
+ @Override
protected String getDimensionServiceKey() {
if (myDimensionKey == null) {
return super.getDimensionServiceKey();
@@ -143,6 +144,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
}
}
+ @Override
@NotNull
protected Action[] createActions() {
List<Action> actions = new ArrayList<Action>();
@@ -157,6 +159,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
return actions.toArray(new Action[actions.size()]);
}
+ @Override
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp(myConfigurable.getHelpTopic());
}
@@ -169,6 +172,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
super.doCancelAction();
}
+ @Override
protected void doOKAction() {
try {
if (myConfigurable.isModified()) myConfigurable.apply();
@@ -201,10 +205,11 @@ public class SingleConfigurableEditor extends DialogWrapper {
public ApplyAction() {
super(CommonBundle.getApplyButtonText());
final Runnable updateRequest = new Runnable() {
+ @Override
public void run() {
- if (!SingleConfigurableEditor.this.isShowing()) return;
+ if (!isShowing()) return;
try {
- ApplyAction.this.setEnabled(myConfigurable != null && myConfigurable.isModified());
+ setEnabled(myConfigurable != null && myConfigurable.isModified());
}
catch (IndexNotReadyException ignored) {
}
@@ -214,6 +219,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
// invokeLater necessary to make sure dialog is already shown so we calculate modality state correctly.
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
addUpdateRequest(updateRequest);
}
@@ -224,6 +230,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
myUpdateAlarm.addRequest(updateRequest, 500, ModalityState.stateForComponent(getWindow()));
}
+ @Override
public void actionPerformed(ActionEvent event) {
if (myPerformAction) return;
try {
@@ -248,11 +255,13 @@ public class SingleConfigurableEditor extends DialogWrapper {
}
}
+ @Override
protected JComponent createCenterPanel() {
myCenterPanel = myConfigurable.createComponent();
return myCenterPanel;
}
+ @Override
public JComponent getPreferredFocusedComponent() {
if (myConfigurable instanceof BaseConfigurable) {
JComponent preferred = ((BaseConfigurable)myConfigurable).getPreferredFocusedComponent();
@@ -261,6 +270,7 @@ public class SingleConfigurableEditor extends DialogWrapper {
return IdeFocusTraversalPolicy.getPreferredFocusedComponent(myCenterPanel);
}
+ @Override
public void dispose() {
super.dispose();
myConfigurable.disposeUIResources();
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
new file mode 100644
index 000000000000..c38bf6ff2033
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.options.newEditor;
+
+import com.intellij.CommonBundle;
+import com.intellij.ide.ui.search.SearchUtil;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.help.HelpManager;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurableGroup;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.ui.Gray;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.border.CustomLineBorder;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class IdeSettingsDialog extends DialogWrapper implements DataProvider {
+ private Project myProject;
+ private ConfigurableGroup[] myGroups;
+ private Configurable myPreselected;
+ private OptionsEditor myEditor;
+
+ private ApplyAction myApplyAction;
+ public static final String DIMENSION_KEY = "OptionsEditor";
+ @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.perProjectModality
+ *
+ * @deprecated
+ */
+ public IdeSettingsDialog(Project project, ConfigurableGroup[] groups,
+ @Nullable Configurable preselectedConfigurable, boolean applicationModalIfPossible) {
+ super(project, true, applicationModalIfPossible);
+ init(project, groups, preselectedConfigurable != null ? preselectedConfigurable : findLastSavedConfigurable(groups, project));
+ }
+
+ /**
+ * This constructor should be eliminated after the new modality approach
+ * will have been checked. See a {@code Registry} key ide.perProjectModality
+ *
+ * @deprecated
+ */
+ public IdeSettingsDialog(Project project, ConfigurableGroup[] groups,
+ @NotNull String preselectedConfigurableDisplayName, boolean applicationModalIfPossible) {
+ super(project, true, applicationModalIfPossible);
+ init(project, groups, getPreselectedByDisplayName(groups, preselectedConfigurableDisplayName, project));
+ }
+
+ public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, @Nullable Configurable preselectedConfigurable) {
+ super(project, true);
+ init(project, groups, preselectedConfigurable != null ? preselectedConfigurable : findLastSavedConfigurable(groups, project));
+ }
+
+ public IdeSettingsDialog(Project project, ConfigurableGroup[] groups, @NotNull String preselectedConfigurableDisplayName) {
+ super(project, true);
+ init(project, groups, getPreselectedByDisplayName(groups, preselectedConfigurableDisplayName, project));
+ }
+
+ @Nullable
+ @Override
+ protected Border createContentPaneBorder() {
+ return IdeBorderFactory.createEmptyBorder(0);
+ }
+
+ private void init(final Project project, final ConfigurableGroup[] groups, @Nullable final Configurable preselected) {
+ myProject = project;
+ myGroups = groups;
+ myPreselected = preselected;
+
+ setTitle(CommonBundle.settingsTitle());
+
+ init();
+ }
+
+ @Nullable
+ private static Configurable getPreselectedByDisplayName(final ConfigurableGroup[] groups, final String preselectedConfigurableDisplayName,
+ final Project project) {
+ Configurable result = findPreselectedByDisplayName(preselectedConfigurableDisplayName, groups);
+
+ return result == null ? findLastSavedConfigurable(groups, project) : result;
+ }
+
+ @Override
+ public boolean isTypeAheadEnabled() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createSouthPanel() {
+ final JComponent panel = super.createSouthPanel();
+ CustomLineBorder line = new CustomLineBorder(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)), 1, 0, 0, 0);
+ panel.setBorder(new CompoundBorder(line, new EmptyBorder(8, 12, 8, 12)));
+ return panel;
+ }
+
+ protected JComponent createCenterPanel() {
+ myEditor = new OptionsEditor(myProject, myGroups, myPreselected);
+ myEditor.getContext().addColleague(new OptionsEditorColleague.Adapter() {
+ @Override
+ public ActionCallback onModifiedAdded(final Configurable configurable) {
+ updateStatus();
+ return new ActionCallback.Done();
+ }
+
+ @Override
+ public ActionCallback onModifiedRemoved(final Configurable configurable) {
+ updateStatus();
+ return new ActionCallback.Done();
+ }
+
+ @Override
+ public ActionCallback onErrorsChanged() {
+ updateStatus();
+ return new ActionCallback.Done();
+ }
+ });
+ Disposer.register(myDisposable, myEditor);
+ return myEditor;
+ }
+
+ public boolean updateStatus() {
+ myApplyAction.setEnabled(myEditor.canApply());
+
+ final Map<Configurable, ConfigurationException> errors = myEditor.getContext().getErrors();
+ if (errors.size() == 0) {
+ setErrorText(null);
+ }
+ else {
+ String text = "Changes were not applied because of an error";
+
+ final String errorMessage = getErrorMessage(errors);
+ if (errorMessage != null) {
+ text += "<br>" + errorMessage;
+ }
+
+ setErrorText(text);
+ }
+
+ return errors.size() == 0;
+ }
+
+ @Nullable
+ private static String getErrorMessage(final Map<Configurable, ConfigurationException> errors) {
+ final Collection<ConfigurationException> values = errors.values();
+ final ConfigurationException[] exceptions = values.toArray(new ConfigurationException[values.size()]);
+ if (exceptions.length > 0) {
+ return exceptions[0].getMessage();
+ }
+ return null;
+ }
+
+ @Override
+ protected String getDimensionServiceKey() {
+ return DIMENSION_KEY;
+ }
+
+ @Override
+ protected void doOKAction() {
+ myEditor.flushModifications();
+
+ if (myEditor.canApply()) {
+ myEditor.apply();
+ if (!updateStatus()) return;
+ }
+
+ saveCurrentConfigurable();
+
+ ApplicationManager.getApplication().saveAll();
+
+ super.doOKAction();
+ }
+
+
+ private void saveCurrentConfigurable() {
+ final Configurable current = myEditor.getContext().getCurrentConfigurable();
+ if (current == null) return;
+
+ final PropertiesComponent props = PropertiesComponent.getInstance(myProject);
+
+ if (current instanceof SearchableConfigurable) {
+ props.setValue(LAST_SELECTED_CONFIGURABLE, ((SearchableConfigurable)current).getId());
+ }
+ else {
+ props.setValue(LAST_SELECTED_CONFIGURABLE, current.getClass().getName());
+ }
+ }
+
+ @Nullable
+ private static Configurable findLastSavedConfigurable(ConfigurableGroup[] groups, final Project project) {
+ final String id = PropertiesComponent.getInstance(project).getValue(LAST_SELECTED_CONFIGURABLE);
+ if (id == null) return null;
+
+ return findConfigurableInGroups(id, groups);
+ }
+
+ @Nullable
+ private static Configurable findConfigurableInGroups(String id, Configurable.Composite... groups) {
+ // avoid unnecessary group expand: check top-level configurables in all groups before looking at children
+ for (Configurable.Composite group : groups) {
+ final Configurable[] configurables = group.getConfigurables();
+ for (Configurable c : configurables) {
+ if (c instanceof SearchableConfigurable && id.equals(((SearchableConfigurable)c).getId())) {
+ return c;
+ }
+ else if (id.equals(c.getClass().getName())) {
+ return c;
+ }
+ }
+ }
+ for (Configurable.Composite group : groups) {
+ final Configurable[] configurables = group.getConfigurables();
+ for (Configurable c : configurables) {
+ if (c instanceof Configurable.Composite) {
+ Configurable result = findConfigurableInGroups(id, (Configurable.Composite)c);
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static Configurable findPreselectedByDisplayName(final String preselectedConfigurableDisplayName, ConfigurableGroup[] groups) {
+ final List<Configurable> all = SearchUtil.expand(groups);
+ for (Configurable each : all) {
+ if (preselectedConfigurableDisplayName.equals(each.getDisplayName())) return each;
+ }
+ return null;
+ }
+
+ @Override
+ public void doCancelAction(final AWTEvent source) {
+ if (source instanceof KeyEvent || source instanceof ActionEvent) {
+ if (myEditor.getContext().isHoldingFilter()) {
+ myEditor.clearFilter();
+ return;
+ }
+ }
+
+ super.doCancelAction(source);
+ }
+
+ @Override
+ public void doCancelAction() {
+ saveCurrentConfigurable();
+ super.doCancelAction();
+ }
+
+ @NotNull
+ @Override
+ protected Action[] createActions() {
+ myApplyAction = new ApplyAction();
+ return new Action[]{getOKAction(), getCancelAction(), myApplyAction, getHelpAction()};
+ }
+
+ @Override
+ protected void doHelpAction() {
+ final String topic = myEditor.getHelpTopic();
+ if (topic != null) {
+ HelpManager.getInstance().invokeHelp(topic);
+ }
+ }
+
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myEditor.getPreferredFocusedComponent();
+ }
+
+ public Object getData(@NonNls String dataId) {
+ if (OptionsEditor.KEY.is(dataId)) {
+ return myEditor;
+ }
+ return null;
+ }
+
+ private class ApplyAction extends AbstractAction {
+ public ApplyAction() {
+ super(CommonBundle.getApplyButtonText());
+ setEnabled(false);
+ }
+
+ public void actionPerformed(final ActionEvent e) {
+ myEditor.apply();
+ myEditor.revalidate();
+ myEditor.repaint();
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
index 271539f038a0..c2119596a06e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
@@ -15,9 +15,12 @@
*/
package com.intellij.openapi.options.newEditor;
-import com.intellij.ide.ui.search.ConfigurableHit;
+import com.intellij.AbstractBundle;
+import com.intellij.CommonBundle;
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
+import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.ide.ui.search.SearchUtil;
-import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
@@ -36,18 +39,18 @@ import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EdtRunnable;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
-import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.LightColors;
+import com.intellij.ui.OnePixelSplitter;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SearchTextField;
+import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.navigation.History;
import com.intellij.ui.navigation.Place;
-import com.intellij.ui.speedSearch.ElementFilter;
import com.intellij.ui.treeStructure.SimpleNode;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.UIUtil;
@@ -61,7 +64,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.event.DocumentEvent;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
@@ -77,23 +80,18 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
@NonNls private static final String MAIN_SPLITTER_PROPORTION = "options.splitter.main.proportions";
@NonNls private static final String DETAILS_SPLITTER_PROPORTION = "options.splitter.details.proportions";
- @NonNls private static final String SEARCH_VISIBLE = "options.searchVisible";
-
@NonNls private static final String NOT_A_NEW_COMPONENT = "component.was.already.instantiated";
- private final Project myProject;
-
- private final OptionsEditorContext myContext;
-
private final History myHistory = new History(this);
private final OptionsTree myTree;
private final SettingsTreeView myTreeView;
- private final MySearchField mySearch;
+ private final SearchTextField mySearch;
private final Splitter myMainSplitter;
//[back/forward] JComponent myToolbarComponent;
- private final DetailsComponent myOwnDetails = new DetailsComponent().setEmptyContentText("Select configuration element in the tree to edit its settings");
+ private final DetailsComponent myOwnDetails =
+ new DetailsComponent().setEmptyContentText("Select configuration element in the tree to edit its settings");
private final ContentWrapper myContentWrapper = new ContentWrapper();
@@ -101,30 +99,54 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
private final Map<Configurable, ActionCallback> myConfigurable2LoadCallback = new HashMap<Configurable, ActionCallback>();
private final MergingUpdateQueue myModificationChecker;
- private final ConfigurableGroup[] myGroups;
private final SpotlightPainter mySpotlightPainter = new SpotlightPainter();
private final MergingUpdateQueue mySpotlightUpdate;
private final LoadingDecorator myLoadingDecorator;
- private final Filter myFilter;
+ private final SettingsFilter myFilter;
private final Wrapper mySearchWrapper = new Wrapper();
private final JPanel myLeftSide;
- private boolean myFilterDocumentWasChanged;
//[back/forward] private ActionToolbar myToolbar;
private Window myWindow;
private final PropertiesComponent myProperties;
private volatile boolean myDisposed;
+ private final KeyListener myTreeKeyListener = new KeyListener() {
+ @Override
+ public void keyPressed(KeyEvent event) {
+ keyTyped(event);
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event) {
+ keyTyped(event);
+ }
+
+ @Override
+ public void keyTyped(KeyEvent event) {
+ Object source = event.getSource();
+ if (source instanceof JTree) {
+ JTree tree = (JTree)source;
+ if (tree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event)) == null) {
+ myFilter.myDocumentWasChanged = false;
+ try {
+ mySearch.keyEventToTextField(event);
+ }
+ finally {
+ if (myFilter.myDocumentWasChanged && !isFilterFieldVisible()) {
+ setFilterFieldVisible(true, false, false);
+ }
+ }
+ }
+ }
+ }
+ };
+
public OptionsEditor(Project project, ConfigurableGroup[] groups, Configurable preselectedConfigurable) {
- myProject = project;
- myGroups = groups;
myProperties = PropertiesComponent.getInstance(project);
- myFilter = new Filter();
- myContext = new OptionsEditorContext(myFilter);
-
mySearch = new MySearchField() {
@Override
protected void onTextKeyEvent(final KeyEvent e) {
@@ -137,67 +159,53 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
};
- mySearch.getTextEditor().addMouseListener(new MouseAdapter() {
- @Override
- public void mousePressed(MouseEvent e) {
- boolean hasText = mySearch.getText().length() > 0;
- if (!myContext.isHoldingFilter() && hasText) {
- myFilter.reenable();
- }
-
- if (!isSearchFieldFocused() && hasText) {
- mySearch.selectText();
- }
- }
- });
-
- final KeyListener listener = new KeyListener() {
+ myFilter = new SettingsFilter(project, groups, mySearch) {
@Override
- public void keyTyped(KeyEvent event) {
- myFilterDocumentWasChanged = false;
- try {
- mySearch.keyEventToTextField(event);
- }
- finally {
- if (myFilterDocumentWasChanged && !isFilterFieldVisible()) {
- setFilterFieldVisible(true, false, false);
- }
+ Configurable getConfigurable(SimpleNode node) {
+ if (node instanceof OptionsTree.EditorNode) {
+ return ((OptionsTree.EditorNode)node).getConfigurable();
}
+ return SettingsTreeView.getConfigurable(node);
}
@Override
- public void keyPressed(KeyEvent event) {
- keyTyped(event);
+ SimpleNode findNode(Configurable configurable) {
+ return myTreeView != null
+ ? myTreeView.findNode(configurable)
+ : myTree.findNodeFor(configurable);
}
@Override
- public void keyReleased(KeyEvent event) {
- keyTyped(event);
+ void updateSpotlight(boolean now) {
+ if (!now) {
+ mySpotlightUpdate.queue(new Update(this) {
+ @Override
+ public void run() {
+ if (!mySpotlightPainter.updateForCurrentConfigurable()) {
+ updateSpotlight(false);
+ }
+ }
+ });
+ }
+ else if (!mySpotlightPainter.updateForCurrentConfigurable()) {
+ updateSpotlight(false);
+ }
}
};
- if (Registry.is("ide.file.settings.tree.new")) {
- myTreeView = new SettingsTreeView(listener, getContext(), groups);
+
+ if (Registry.is("ide.new.settings.dialog")) {
+ myTreeView = new SettingsTreeView(myFilter, groups);
+ myTreeView.myTree.addKeyListener(myTreeKeyListener);
myTree = null;
}
else {
myTreeView = null;
- myTree = new OptionsTree(myProject, groups, getContext()) {
- @Override
- protected void onTreeKeyEvent(final KeyEvent e) {
- listener.keyTyped(e);
- }
- };
+ myTree = new OptionsTree(myFilter, groups);
+ myTree.addKeyListener(myTreeKeyListener);
}
getContext().addColleague(myTreeView != null ? myTreeView : myTree);
Disposer.register(this, myTreeView != null ? myTreeView : myTree);
- mySearch.addDocumentListener(new DocumentAdapter() {
- @Override
- protected void textChanged(DocumentEvent e) {
- myFilter.update(e.getType(), true, false);
- }
- });
-
/* [back/forward]
final DefaultActionGroup toolbarActions = new DefaultActionGroup();
@@ -246,7 +254,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
setLayout(new BorderLayout());
- myMainSplitter = new Splitter(false);
+ myMainSplitter = Registry.is("ide.new.settings.dialog") ? new OnePixelSplitter(false) : new Splitter(false);
myMainSplitter.setFirstComponent(myLeftSide);
myLoadingDecorator = new LoadingDecorator(myOwnDetails.getComponent(), this, 150);
@@ -264,13 +272,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
mySpotlightUpdate = new MergingUpdateQueue("OptionsSpotlight", 200, false, this, this, this);
if (preselectedConfigurable != null) {
- if (myTreeView != null) {
- myTreeView.select(preselectedConfigurable);
- }
- else {
- myTree.select(preselectedConfigurable);
- }
- } else {
+ selectInTree(preselectedConfigurable);
+ }
+ else {
if (myTreeView != null) {
myTreeView.selectFirst();
}
@@ -322,6 +326,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
});
}
+ private ActionCallback selectInTree(Configurable configurable) {
+ return myTreeView != null
+ ? myTreeView.select(configurable)
+ : myTree.select(configurable);
+ }
+
/** @see #select(com.intellij.openapi.options.Configurable) */
@Deprecated
public ActionCallback select(Class<? extends Configurable> configurableClass) {
@@ -354,18 +364,17 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
public ActionCallback select(Configurable configurable) {
- if (StringUtil.isEmpty(mySearch.getText())) {
+ if (myFilter.getFilterText().isEmpty()) {
return select(configurable, "");
- } else {
- return myFilter.refilterFor(mySearch.getText(), true, true);
+ }
+ else {
+ return myFilter.update(true, true);
}
}
public ActionCallback select(Configurable configurable, final String text) {
- myFilter.refilterFor(text, false, true);
- return myTreeView != null
- ? myTreeView.select(configurable)
- : myTree.select(configurable);
+ myFilter.update(text, false, true);
+ return selectInTree(configurable);
}
private float readProportion(final float defaultValue, final String propertyName) {
@@ -390,7 +399,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
if (configurable == null) {
myOwnDetails.setContent(null);
- updateSpotlight(true);
+ myFilter.updateSpotlight(true);
checkModified(oldConfigurable);
result.setDone();
@@ -417,7 +426,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
if (myTreeView != null) {
myOwnDetails.forProject(myTreeView.findConfigurableProject(configurable));
}
- else if (Registry.is("ide.file.settings.order.new")) {
+ else if (Registry.is("ide.new.settings.dialog")) {
myOwnDetails.forProject(myTree.getConfigurableProject(configurable));
}
@@ -430,7 +439,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myLoadingDecorator.stopLoading();
- updateSpotlight(false);
+ myFilter.updateSpotlight(false);
checkModified(oldConfigurable);
checkModified(configurable);
@@ -480,7 +489,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
((ApplicationEx)app).runEdtSafeAction(new Runnable() {
@Override
public void run() {
- if (myProject.isDisposed()) {
+ if (myFilter.myProject.isDisposed()) {
result.setRejected();
}
else {
@@ -537,26 +546,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
return result;
}
-
- private void updateSpotlight(boolean now) {
- if (now) {
- final boolean success = mySpotlightPainter.updateForCurrentConfigurable();
- if (!success) {
- updateSpotlight(false);
- }
- } else {
- mySpotlightUpdate.queue(new Update(this) {
- @Override
- public void run() {
- final boolean success = mySpotlightPainter.updateForCurrentConfigurable();
- if (!success) {
- updateSpotlight(false);
- }
- }
- });
- }
- }
-
private String[] getBannerText(Configurable configurable) {
if (myTreeView != null) {
return myTreeView.getPathNames(configurable);
@@ -712,7 +701,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
@Override
public boolean isEnabled() {
- return myContext.isModified(myConfigurable) || getContext().getErrors().containsKey(myConfigurable);
+ return myFilter.myContext.isModified(myConfigurable) || getContext().getErrors().containsKey(myConfigurable);
}
}
@@ -849,12 +838,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
getContext().fireErrorsChanged(errors, null);
if (!errors.isEmpty()) {
- if (myTreeView != null) {
- myTreeView.select(errors.keySet().iterator().next());
- }
- else {
- myTree.select(errors.keySet().iterator().next());
- }
+ selectInTree(errors.keySet().iterator().next());
}
}
@@ -868,7 +852,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
public JComponent getPreferredFocusedComponent() {
- return mySearch;//myTree.getTree();
+ return myTreeView != null ? myTreeView.myTree : mySearch;//myTree.getTree();
}
@Override
@@ -876,145 +860,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
return new Dimension(1200, 768);
}
- private class Filter extends ElementFilter.Active.Impl<SimpleNode> {
-
- SearchableOptionsRegistrar myIndex = SearchableOptionsRegistrar.getInstance();
- Set<Configurable> myFiltered = null;
- ConfigurableHit myHits;
-
- boolean myUpdateEnabled = true;
- private Configurable myLastSelected;
-
- @Override
- public boolean shouldBeShowing(final SimpleNode value) {
- if (myFiltered == null) return true;
-
- if (value instanceof OptionsTree.EditorNode) {
- final OptionsTree.EditorNode node = (OptionsTree.EditorNode)value;
- return myFiltered.contains(node.getConfigurable()) || isChildOfNameHit(node);
- }
-
- return SettingsTreeView.isFiltered(myFiltered, myHits, value);
- }
-
- private boolean isChildOfNameHit(OptionsTree.EditorNode node) {
- if (myHits != null) {
- OptionsTree.Base eachParent = node;
- while (eachParent != null) {
- if (eachParent instanceof OptionsTree.EditorNode) {
- final OptionsTree.EditorNode eachEditorNode = (OptionsTree.EditorNode)eachParent;
- if (myHits.getNameFullHits().contains(eachEditorNode.myConfigurable)) return true;
- }
- eachParent = (OptionsTree.Base)eachParent.getParent();
- }
-
- return false;
- }
-
- return false;
- }
-
- public ActionCallback refilterFor(String text, boolean adjustSelection, final boolean now) {
- try {
- myUpdateEnabled = false;
- mySearch.setText(text);
- }
- finally {
- myUpdateEnabled = true;
- }
-
- return update(DocumentEvent.EventType.CHANGE, adjustSelection, now);
- }
-
- public void clearTemporary() {
- myContext.setHoldingFilter(false);
- updateSpotlight(false);
- }
-
- public void reenable() {
- myContext.setHoldingFilter(true);
- updateSpotlight(false);
- }
-
- public ActionCallback update(DocumentEvent.EventType type, boolean adjustSelection, boolean now) {
- if (!myUpdateEnabled) return new ActionCallback.Rejected();
-
- final String text = mySearch.getText();
- if (getFilterText().length() == 0) {
- myContext.setHoldingFilter(false);
- myFiltered = null;
- } else {
- myContext.setHoldingFilter(true);
- myHits = myIndex.getConfigurables(myGroups, type, myFiltered, text, myProject);
- myFiltered = myHits.getAll();
- }
-
- if (myFiltered != null && myFiltered.isEmpty()) {
- mySearch.getTextEditor().setBackground(LightColors.RED);
- } else {
- mySearch.getTextEditor().setBackground(UIUtil.getTextFieldBackground());
- }
-
-
- final Configurable current = getContext().getCurrentConfigurable();
-
- boolean shouldMoveSelection = true;
-
- if (myHits != null && (myHits.getNameFullHits().contains(current) || myHits.getContentHits().contains(current))) {
- shouldMoveSelection = false;
- }
-
- if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (myFiltered == null || myFiltered.contains(current))) {
- shouldMoveSelection = false;
- }
-
- Configurable toSelect = adjustSelection ? current : null;
- if (shouldMoveSelection && myHits != null) {
- if (!myHits.getNameHits().isEmpty()) {
- toSelect = suggestToSelect(myHits.getNameHits(), myHits.getNameFullHits());
- } else if (!myHits.getContentHits().isEmpty()) {
- toSelect = suggestToSelect(myHits.getContentHits(), null);
- }
- }
-
- updateSpotlight(false);
-
- if ((myFiltered == null || !myFiltered.isEmpty()) && toSelect == null && myLastSelected != null) {
- toSelect = myLastSelected;
- myLastSelected = null;
- }
-
- if (toSelect == null && current != null) {
- myLastSelected = current;
- }
-
- SimpleNode node = !adjustSelection ? null : myTreeView != null ? myTreeView.findNode(toSelect) : myTree.findNodeFor(toSelect);
- final ActionCallback callback = fireUpdate(node, adjustSelection, now);
-
- myFilterDocumentWasChanged = true;
-
- return callback;
- }
-
- private boolean isEmptyParent(Configurable configurable) {
- return configurable instanceof SearchableConfigurable.Parent && !((SearchableConfigurable.Parent)configurable).hasOwnContent();
- }
-
- @Nullable
- private Configurable suggestToSelect(Set<Configurable> set, Set<Configurable> fullHits) {
- Configurable candidate = null;
- for (Configurable each : set) {
- if (fullHits != null && fullHits.contains(each)) return each;
- if (!isEmptyParent(each) && candidate == null) {
- candidate = each;
- }
- }
-
- return candidate;
- }
-
- }
-
@Override
public ActionCallback navigateTo(@Nullable final Place place, final boolean requestFocus) {
final Configurable config = (Configurable)place.getPath("configurable");
@@ -1022,15 +867,10 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
final ActionCallback result = new ActionCallback();
- myFilter.refilterFor(filter, false, true).doWhenDone(new Runnable() {
+ myFilter.update(filter, false, true).doWhenDone(new Runnable() {
@Override
public void run() {
- if (myTreeView != null) {
- myTreeView.select(config).notifyWhenDone(result);
- }
- else {
- myTree.select(config).notifyWhenDone(result);
- }
+ selectInTree(config).notifyWhenDone(result);
}
});
@@ -1041,7 +881,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
public void queryPlace(@NotNull final Place place) {
final Configurable current = getContext().getCurrentConfigurable();
place.putPath("configurable", current);
- place.putPath("filter", getFilterText());
+ place.putPath("filter", myFilter.getFilterText());
if (current instanceof Place.Navigator) {
((Place.Navigator)current).queryPlace(place);
@@ -1060,7 +900,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myProperties.setValue(MAIN_SPLITTER_PROPORTION, String.valueOf(myMainSplitter.getProportion()));
myProperties.setValue(DETAILS_SPLITTER_PROPORTION, String.valueOf(myContentWrapper.myLastSplitterProportion));
- myProperties.setValue(SEARCH_VISIBLE, Boolean.valueOf(isFilterFieldVisible()).toString());
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
@@ -1087,7 +926,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
public OptionsEditorContext getContext() {
- return myContext;
+ return myFilter.myContext;
}
private class MyColleague extends OptionsEditorColleague.Adapter {
@@ -1137,7 +976,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
final MouseEvent me = (MouseEvent)event;
if (SwingUtilities.isDescendingFrom(me.getComponent(), SwingUtilities.getWindowAncestor(myContentWrapper)) || isPopupOverEditor(me.getComponent())) {
queueModificationCheck();
- myFilter.clearTemporary();
+ myFilter.setHoldingFilter(false);
}
}
else if (event.getID() == KeyEvent.KEY_PRESSED || event.getID() == KeyEvent.KEY_RELEASED) {
@@ -1175,6 +1014,23 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
private MySearchField() {
super(false);
addKeyListener(new KeyAdapter() {});
+ if (Registry.is("ide.new.settings.dialog")) {
+ final JTextField editor = getTextEditor();
+ if (!SystemInfo.isMac) {
+ editor.putClientProperty("JTextField.variant", "search");
+ if (!(editor.getUI() instanceof DarculaTextFieldUI)) {
+ editor.setUI((DarculaTextFieldUI)DarculaTextFieldUI.createUI(editor));
+ editor.setBorder(new DarculaTextBorder());
+ }
+ }
+ setBackground(UIUtil.getSidePanelColor());
+ setBorder(new EmptyBorder(5, 10, 2, 10));
+ }
+ }
+
+ @Override
+ protected boolean isSearchControlUISupported() {
+ return true;
}
@Override
@@ -1236,7 +1092,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
return ApplicationManager.getApplication().isUnitTestMode();
}
- String text = getFilterText();
+ String text = myFilter.getFilterText();
try {
final boolean sameText =
@@ -1263,14 +1119,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myVisible = true;//myContext.isHoldingFilter();
runnable.run();
- boolean pushFilteringFurther = true;
- if (sameText) {
- pushFilteringFurther = false;
- } else {
- if (myFilter.myHits != null) {
- pushFilteringFurther = !myFilter.myHits.getNameHits().contains(current);
- }
- }
+ boolean pushFilteringFurther = !sameText && !myFilter.contains(current);
final Runnable ownSearch = searchable.enableSearch(text);
if (pushFilteringFurther && ownSearch != null) {
@@ -1295,10 +1144,6 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
}
- private String getFilterText() {
- return mySearch.getText() != null ? mySearch.getText().trim() : "";
- }
-
private static class SearachableWrappper implements SearchableConfigurable {
private final Configurable myConfigurable;
@@ -1366,6 +1211,49 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
abstract void setText(final String[] bannerText);
}
+ /**
+ * Returns default view for the specified configurable.
+ * It uses the configurable identifier to retrieve description.
+ *
+ * @param searchable the configurable that does not have any view
+ * @return default view for the specified configurable
+ */
+ private JComponent createDefaultComponent(SearchableConfigurable searchable) {
+ JPanel box = new JPanel();
+ box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
+ try {
+ box.add(new JLabel(getDefaultDescription(searchable)));
+ }
+ catch (AssertionError error) {
+ return null; // description is not set
+ }
+ if (searchable instanceof Configurable.Composite) {
+ box.add(Box.createVerticalStrut(10));
+ Configurable.Composite composite = (Configurable.Composite)searchable;
+ for (final Configurable configurable : composite.getConfigurables()) {
+ box.add(new LinkLabel(configurable.getDisplayName(), AllIcons.Ide.Link) {
+ @Override
+ public void doClick() {
+ select(configurable, null);
+ }
+ });
+ }
+ }
+ return box;
+ }
+
+ @NotNull
+ private static String getDefaultDescription(SearchableConfigurable configurable) {
+ String key = configurable.getId() + ".settings.description";
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper) configurable;
+ ConfigurableEP ep = wrapper.getExtensionPoint();
+ ResourceBundle resourceBundle = AbstractBundle.getResourceBundle(ep.bundle, ep.getPluginDescriptor().getPluginClassLoader());
+ return CommonBundle.message(resourceBundle, key);
+ }
+ return OptionsBundle.message(key);
+ }
+
private class Simple extends ConfigurableContent {
JComponent myComponent;
Configurable myConfigurable;
@@ -1373,7 +1261,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
Simple(final Configurable configurable) {
myConfigurable = configurable;
myComponent = configurable.createComponent();
-
+ if (myComponent == null && configurable instanceof SearchableConfigurable) {
+ myComponent = createDefaultComponent((SearchableConfigurable)configurable);
+ }
if (myComponent != null) {
final Object clientProperty = myComponent.getClientProperty(NOT_A_NEW_COMPONENT);
if (clientProperty != null && ApplicationManager.getApplication().isInternal()) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
index 175b994122ef..aee9e889fdf1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
@@ -37,6 +37,7 @@ import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.util.ui.tree.WideSelectionTreeUI;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NotNull;
@@ -49,33 +50,32 @@ import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.TreeUI;
-import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
-import java.awt.event.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
public class OptionsTree extends JPanel implements Disposable, OptionsEditorColleague {
- Project myProject;
+ private final SettingsFilter myFilter;
final SimpleTree myTree;
List<ConfigurableGroup> myGroups;
FilteringTreeBuilder myBuilder;
Root myRoot;
- OptionsEditorContext myContext;
Map<Configurable, EditorNode> myConfigurable2Node = new HashMap<Configurable, EditorNode>();
MergingUpdateQueue mySelection;
private final OptionsTree.Renderer myRenderer;
- public OptionsTree(Project project, ConfigurableGroup[] groups, OptionsEditorContext context) {
- myProject = project;
+ public OptionsTree(SettingsFilter filter, ConfigurableGroup... groups) {
+ myFilter = filter;
myGroups = Arrays.asList(groups);
- myContext = context;
-
myRoot = new Root();
final SimpleTreeStructure structure = new SimpleTreeStructure() {
@@ -132,35 +132,8 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
}
});
- myTree.addKeyListener(new KeyListener() {
- public void keyTyped(final KeyEvent e) {
- _onTreeKeyEvent(e);
- }
-
- public void keyPressed(final KeyEvent e) {
- _onTreeKeyEvent(e);
- }
-
- public void keyReleased(final KeyEvent e) {
- _onTreeKeyEvent(e);
- }
- });
- }
-
- protected void _onTreeKeyEvent(KeyEvent e) {
- final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e);
-
- final Object action = myTree.getInputMap().get(stroke);
- if (action == null) {
- onTreeKeyEvent(e);
- }
- }
-
- protected void onTreeKeyEvent(KeyEvent e) {
-
}
-
ActionCallback select(@Nullable Configurable configurable) {
return queueSelection(configurable);
}
@@ -191,7 +164,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
if (configurable == null) {
myTree.getSelectionModel().clearSelection();
- myContext.fireSelected(null, OptionsTree.this);
+ myFilter.myContext.fireSelected(null, OptionsTree.this);
}
else {
myBuilder.getReady(this).doWhenDone(new Runnable() {
@@ -232,7 +205,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
private void fireSelected(Configurable configurable, final ActionCallback callback) {
- myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
+ myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
}
@@ -297,7 +270,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
myRendererComponent.setOpaqueActive(false);
mySeparator = new GroupSeparator();
- myRendererComponent.add(Registry.is("ide.file.settings.order.new") ? mySeparator : mySeparatorComponent, BorderLayout.NORTH);
+ myRendererComponent.add(Registry.is("ide.new.settings.dialog") ? mySeparator : mySeparatorComponent, BorderLayout.NORTH);
final NonOpaquePanel content = new NonOpaquePanel(new BorderLayout());
myHandle = new JLabel("", SwingConstants.CENTER);
@@ -401,12 +374,12 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground() : fg);
myTextLabel.setOpaque(selected);
- if (Registry.is("ide.file.settings.order.new")) {
+ if (Registry.is("ide.new.settings.dialog")) {
myTextLabel.setBorder(new EmptyBorder(1,2,1,0));
}
Project project = null;
- if (base != null && Registry.is("ide.file.settings.order.new")) {
+ if (base != null && Registry.is("ide.new.settings.dialog")) {
SimpleNode parent = base.getParent();
if (parent == myRoot) {
project = getConfigurableProject(base); // show icon for top-level nodes
@@ -433,6 +406,9 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
} else {
myProjectIcon.setVisible(false);
}
+ if (Registry.is("ide.new.settings.dialog")) {
+ result.setBackground(selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getSidePanelColor());
+ }
return result;
}
@@ -538,7 +514,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
final List<EditorNode> result = new ArrayList<EditorNode>(kids.length);
for (Configurable child : kids) {
result.add(new EditorNode(parent, child, group));
- myContext.registerKid(configurable, child);
+ myFilter.myContext.registerKid(configurable, child);
}
return result; // TODO: DECIDE IF INNERS SHOULD BE SORTED: sort(result);
}
@@ -602,12 +578,12 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
@Override
boolean isModified() {
- return myContext.getModified().contains(myConfigurable);
+ return myFilter.myContext.getModified().contains(myConfigurable);
}
@Override
boolean isError() {
- return myContext.getErrors().containsKey(myConfigurable);
+ return myFilter.myContext.getErrors().containsKey(myConfigurable);
}
}
@@ -757,7 +733,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
super.processMouseEvent(e);
}
- private class MyTreeUi extends BasicTreeUI {
+ private class MyTreeUi extends WideSelectionTreeUI {
@Override
public void toggleExpandState(final TreePath path) {
@@ -810,7 +786,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
boolean myWasHoldingFilter;
public MyBuilder(SimpleTreeStructure structure) {
- super(OptionsTree.this.myTree, myContext.getFilter(), structure, new WeightBasedComparator(false));
+ super(myTree, myFilter, structure, new WeightBasedComparator(false));
myTree.addTreeExpansionListener(new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent event) {
invalidateExpansions();
@@ -835,7 +811,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
@Override
public boolean isAutoExpandNode(final NodeDescriptor nodeDescriptor) {
- return myContext.isHoldingFilter();
+ return myFilter.myContext.isHoldingFilter();
}
@Override
@@ -846,21 +822,21 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
@Override
protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) {
final List<Object> toRestore = new ArrayList<Object>();
- if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) {
+ if (myFilter.myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) {
myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements();
- } else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) {
+ } else if (!myFilter.myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) {
toRestore.addAll(myToExpandOnResetFilter);
myToExpandOnResetFilter = null;
}
- myWasHoldingFilter = myContext.isHoldingFilter();
+ myWasHoldingFilter = myFilter.myContext.isHoldingFilter();
ActionCallback result = super.refilterNow(preferredSelection, adjustSelection);
myRefilteringNow = true;
return result.doWhenDone(new Runnable() {
public void run() {
myRefilteringNow = false;
- if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) {
+ if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) {
restoreExpandedState(toRestore);
}
}
@@ -968,7 +944,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
public void paint(Graphics g) {
super.paint(g);
- if (Registry.is("ide.file.settings.order.new")) {
+ if (Registry.is("ide.new.settings.dialog")) {
ConfigurableGroup group = getGroup(GroupSeparator.SPACE + mySeparator.getFont().getSize());
if (group != null && group == getGroup(-GroupSeparator.SPACE)) {
mySeparator.configure(group, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.form b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.form
deleted file mode 100644
index bfd8e1f0e416..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.form
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.options.newEditor.PreferencesDialog">
- <grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
- <constraints>
- <xy x="20" y="20" width="500" height="400"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <grid id="81fb6" binding="myTopPanel" custom-create="true" layout-manager="BorderLayout" hgap="0" vgap="0">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
- <preferred-size width="-1" height="50"/>
- </grid>
- </constraints>
- <properties/>
- <border type="none"/>
- <children/>
- </grid>
- <vspacer id="420b1">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
- </constraints>
- </vspacer>
- <grid id="b87b5" binding="myCenterPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children/>
- </grid>
- <hspacer id="e2eff">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
- </children>
- </grid>
-</form>
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.java
deleted file mode 100644
index 8ed3527e090a..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/PreferencesDialog.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options.newEditor;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.options.ConfigurableGroup;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.ui.Gray;
-import com.intellij.ui.SearchTextField;
-import com.intellij.ui.border.CustomLineBorder;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.border.EmptyBorder;
-import javax.swing.border.LineBorder;
-import java.awt.*;
-
-/**
- * @author Konstantin Bulenkov
- */
-public class PreferencesDialog extends DialogWrapper {
- private JPanel myRoot;
- private JPanel myTopPanel;
- private JPanel myCenterPanel;
- private SearchTextField mySearchTextField;
-
- public PreferencesDialog(@Nullable Project project, ConfigurableGroup[] groups) {
- super(project);
- init();
- ((JDialog)getPeer().getWindow()).setUndecorated(true);
- if (SystemInfo.isMac) {
- ((JComponent)((JDialog)getPeer().getWindow()).getContentPane()).setBorder(new EmptyBorder(0, 0, 0, 0));
- }
- else {
- ((JComponent)((JDialog)getPeer().getWindow()).getContentPane()).setBorder(new LineBorder(Gray._140, 1));
- }
-
- setTitle("Preferences");
- }
-
- @Nullable
- @Override
- protected JComponent createCenterPanel() {
- final JPanel panel = new JPanel();
- panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
- panel.setBorder(null);
- panel.add(createApplicationSettings());
- panel.add(createProjectSettings());
- panel.add(createEditorSettings());
- panel.add(createOtherSettings());
- panel.setPreferredSize(new Dimension(700, 370));
- myCenterPanel.add(panel, BorderLayout.CENTER);
- return myRoot;
- }
-
- @Nullable
- @Override
- public JComponent getPreferredFocusedComponent() {
- return mySearchTextField.getTextEditor();
- }
-
- private static JComponent createEditorSettings() {
- final LabeledButtonsPanel panel = new LabeledButtonsPanel("Editor");
- panel.addButton(new PreferenceButton("Editor", AllIcons.Preferences.Editor));
- panel.addButton(new PreferenceButton("Code Style", AllIcons.Preferences.CodeStyle));
- panel.setBackground(Gray._229);
- panel.setBorder(new CustomLineBorder(Gray._223, 0, 0, 1, 0));
- return panel;
- }
-
- private static JComponent createProjectSettings() {
- final LabeledButtonsPanel panel = new LabeledButtonsPanel("Project");
- panel.addButton(new PreferenceButton("Compiler", AllIcons.Preferences.Compiler));
- panel.addButton(new PreferenceButton("Version Control", AllIcons.Preferences.VersionControl));
- panel.addButton(new PreferenceButton("File Colors", AllIcons.Preferences.FileColors));
- panel.addButton(new PreferenceButton("Scopes", AllIcons.Preferences.Editor));
- panel.setBackground(Gray._236);
- panel.setBorder(new CustomLineBorder(Gray._223, 0, 0, 1, 0));
- return panel;
- }
-
- private static JComponent createApplicationSettings() {
- final LabeledButtonsPanel panel = new LabeledButtonsPanel("IDE");
- panel.addButton(new PreferenceButton("Appearance", AllIcons.Preferences.Appearance));
- panel.addButton(new PreferenceButton("General", AllIcons.Preferences.General));
- panel.addButton(new PreferenceButton("Keymap", AllIcons.Preferences.Keymap));
- panel.addButton(new PreferenceButton("File Types", AllIcons.Preferences.FileTypes));
- panel.setBackground(Gray._229);
- panel.setBorder(new CustomLineBorder(Gray._223, 0, 0, 1, 0));
- return panel;
- }
-
- private static JComponent createOtherSettings() {
- final LabeledButtonsPanel panel = new LabeledButtonsPanel("Other");
- panel.addButton(new PreferenceButton("Plugins", AllIcons.Preferences.Plugins));
- panel.addButton(new PreferenceButton("Updates", AllIcons.Preferences.Updates));
- panel.setBackground(Gray._236);
- panel.setBorder(new CustomLineBorder(Gray._223, 0, 0, 1, 0));
- return panel;
- }
-
-
- @Nullable
- @Override
- protected JComponent createSouthPanel() {
- if (SystemInfo.isMac) {
- return null;
- }
- final JComponent panel = super.createSouthPanel();
- if (panel != null) {
- panel.setBorder(new EmptyBorder(5, 5, 10, 20));
- }
- return panel;
- }
-
- private void createUIComponents() {
- myTopPanel = new JPanel(new BorderLayout()) {
- @Override
- protected void paintComponent(Graphics g) {
- ((Graphics2D)g).setPaint(new GradientPaint(0, 0, Gray._206, 0, getHeight() - 1, Gray._172));
- g.fillRect(0, 0, getWidth(), getHeight());
- g.setColor(Gray._145);
- g.drawLine(0, getHeight() - 2, getWidth(), getHeight() - 2);
- g.setColor(Gray._103);
- g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1);
- }
- };
- final JLabel title = new JLabel("Preferences");
- if (!SystemInfo.isMac) {
- title.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD, 14));
- }
- else {
- title.setFont(new Font("Lucuda Grande", Font.PLAIN, 12));
- }
- title.setHorizontalTextPosition(SwingConstants.CENTER);
- title.setHorizontalAlignment(SwingConstants.CENTER);
- title.setVerticalAlignment(SwingConstants.TOP);
- myTopPanel.add(title, BorderLayout.NORTH);
- mySearchTextField = new SearchTextField();
- mySearchTextField.setOpaque(false);
- myTopPanel.add(mySearchTextField, BorderLayout.EAST);
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java
new file mode 100644
index 000000000000..1885a852c5da
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsFilter.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2000-2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.options.newEditor;
+
+import com.intellij.ide.ui.search.ConfigurableHit;
+import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurableGroup;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.LightColors;
+import com.intellij.ui.SearchTextField;
+import com.intellij.ui.speedSearch.ElementFilter;
+import com.intellij.ui.treeStructure.SimpleNode;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.event.DocumentEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Set;
+
+abstract class SettingsFilter extends ElementFilter.Active.Impl<SimpleNode> {
+ final OptionsEditorContext myContext = new OptionsEditorContext(this);
+ final Project myProject;
+
+ boolean myDocumentWasChanged;
+
+ private final SearchTextField mySearch;
+ private final ConfigurableGroup[] myGroups;
+
+ private SearchableOptionsRegistrar myRegistrar = SearchableOptionsRegistrar.getInstance();
+ private Set<Configurable> myFiltered;
+ private ConfigurableHit myHits;
+
+ private boolean myUpdateRejected;
+ private Configurable myLastSelected;
+
+ SettingsFilter(Project project, ConfigurableGroup[] groups, SearchTextField search) {
+ myProject = project;
+ myGroups = groups;
+ mySearch = search;
+ mySearch.addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent event) {
+ update(event.getType(), true, false);
+ }
+ });
+ mySearch.getTextEditor().addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent event) {
+ if (!mySearch.getText().isEmpty()) {
+ if (!myContext.isHoldingFilter()) {
+ setHoldingFilter(true);
+ }
+ if (!mySearch.getTextEditor().isFocusOwner()) {
+ mySearch.selectText();
+ }
+ }
+ }
+ });
+ }
+
+ abstract Configurable getConfigurable(SimpleNode node);
+
+ abstract SimpleNode findNode(Configurable configurable);
+
+ abstract void updateSpotlight(boolean now);
+
+ @Override
+ public boolean shouldBeShowing(SimpleNode node) {
+ if (myFiltered != null) {
+ Configurable configurable = getConfigurable(node);
+ if (configurable != null) {
+ if (!myFiltered.contains(configurable)) {
+ if (myHits != null) {
+ Set<Configurable> configurables = myHits.getNameFullHits();
+ while (node != null) {
+ if (configurable != null) {
+ if (configurables.contains(configurable)) {
+ return true;
+ }
+ }
+ node = node.getParent();
+ configurable = getConfigurable(node);
+ }
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ String getFilterText() {
+ String text = mySearch.getText();
+ return text == null ? "" : text.trim();
+ }
+
+ void setHoldingFilter(boolean holding) {
+ myContext.setHoldingFilter(holding);
+ updateSpotlight(false);
+ }
+
+ boolean contains(Configurable configurable) {
+ return myHits != null && myHits.getNameHits().contains(configurable);
+ }
+
+ ActionCallback update(boolean adjustSelection, boolean now) {
+ return update(DocumentEvent.EventType.CHANGE, adjustSelection, now);
+ }
+
+ ActionCallback update(String text, boolean adjustSelection, boolean now) {
+ try {
+ myUpdateRejected = true;
+ mySearch.setText(text);
+ }
+ finally {
+ myUpdateRejected = false;
+ }
+ return update(adjustSelection, now);
+ }
+
+ private ActionCallback update(DocumentEvent.EventType type, boolean adjustSelection, boolean now) {
+ if (myUpdateRejected) {
+ return new ActionCallback.Rejected();
+ }
+ String text = getFilterText();
+ if (text.isEmpty()) {
+ myContext.setHoldingFilter(false);
+ myFiltered = null;
+ }
+ else {
+ myContext.setHoldingFilter(true);
+ myHits = myRegistrar.getConfigurables(myGroups, type, myFiltered, text, myProject);
+ myFiltered = myHits.getAll();
+ }
+ mySearch.getTextEditor().setBackground(myFiltered != null && myFiltered.isEmpty()
+ ? LightColors.RED
+ : UIUtil.getTextFieldBackground());
+
+
+ Configurable current = myContext.getCurrentConfigurable();
+
+ boolean shouldMoveSelection = myHits == null || (
+ !myHits.getNameFullHits().contains(current) &&
+ !myHits.getContentHits().contains(current));
+
+ if (shouldMoveSelection && type != DocumentEvent.EventType.INSERT && (myFiltered == null || myFiltered.contains(current))) {
+ shouldMoveSelection = false;
+ }
+
+ Configurable candidate = adjustSelection ? current : null;
+ if (shouldMoveSelection && myHits != null) {
+ if (!myHits.getNameHits().isEmpty()) {
+ candidate = findConfigurable(myHits.getNameHits(), myHits.getNameFullHits());
+ }
+ else if (!myHits.getContentHits().isEmpty()) {
+ candidate = findConfigurable(myHits.getContentHits(), null);
+ }
+ }
+ updateSpotlight(false);
+
+ if ((myFiltered == null || !myFiltered.isEmpty()) && candidate == null && myLastSelected != null) {
+ candidate = myLastSelected;
+ myLastSelected = null;
+ }
+ if (candidate == null && current != null) {
+ myLastSelected = current;
+ }
+ SimpleNode node = !adjustSelection ? null : findNode(candidate);
+ ActionCallback callback = fireUpdate(node, adjustSelection, now);
+ myDocumentWasChanged = true;
+ return callback;
+ }
+
+ private static Configurable findConfigurable(Set<Configurable> configurables, Set<Configurable> hits) {
+ Configurable candidate = null;
+ for (Configurable configurable : configurables) {
+ if (hits != null && hits.contains(configurable)) {
+ return configurable;
+ }
+ if (candidate == null && !isEmptyParent(configurable)) {
+ candidate = configurable;
+ }
+ }
+ return candidate;
+ }
+
+ private static boolean isEmptyParent(Configurable configurable) {
+ if (configurable instanceof SearchableConfigurable.Parent) {
+ SearchableConfigurable.Parent parent = (SearchableConfigurable.Parent)configurable;
+ return !parent.hasOwnContent();
+ }
+ return false;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
index 9269da7ab967..e10367d583bf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.options.newEditor;
import com.intellij.icons.AllIcons;
-import com.intellij.ide.ui.search.ConfigurableHit;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.*;
@@ -26,55 +25,68 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.*;
-import com.intellij.ui.treeStructure.*;
+import com.intellij.ui.treeStructure.CachingSimpleNode;
+import com.intellij.ui.treeStructure.SimpleNode;
+import com.intellij.ui.treeStructure.SimpleTree;
+import com.intellij.ui.treeStructure.SimpleTreeStructure;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ui.ButtonlessScrollBarUI;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.util.ui.tree.WideSelectionTreeUI;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.awt.*;
-import java.awt.event.*;
-import java.util.*;
-import java.util.List;
import javax.swing.*;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.TreeUI;
-import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
+import java.awt.*;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.*;
+import java.util.List;
/**
* @author Sergey.Malenkov
*/
final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague {
+ private static final Color NORMAL_NODE = new JBColor(Gray._60, Gray._140);
+ private static final Color WRONG_CONTENT = JBColor.RED;
+ private static final Color MODIFIED_CONTENT = JBColor.BLUE;
+
final SimpleTree myTree;
final FilteringTreeBuilder myBuilder;
- private final OptionsEditorContext myContext;
+ private final SettingsFilter myFilter;
private final MyRoot myRoot;
private final JScrollPane myScroller;
private JLabel mySeparator;
private final MyRenderer myRenderer = new MyRenderer();
private final IdentityHashMap<Configurable, MyNode> myConfigurableToNodeMap = new IdentityHashMap<Configurable, MyNode>();
- private final MergingUpdateQueue myQueue = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true);
+ private final MergingUpdateQueue myQueue = new MergingUpdateQueue("SettingsTreeView", 150, false, this, this, this)
+ .setRestartTimerOnAdd(true);
private Configurable myQueuedConfigurable;
- SettingsTreeView(final KeyListener listener, OptionsEditorContext context, ConfigurableGroup... groups) {
- myContext = context;
+ SettingsTreeView(SettingsFilter filter, ConfigurableGroup... groups) {
+ myFilter = filter;
myRoot = new MyRoot(groups);
-
myTree = new MyTree();
+ myTree.putClientProperty(WideSelectionTreeUI.TREE_TABLE_TREE_KEY, Boolean.TRUE);
+ myTree.setBackground(UIUtil.getSidePanelColor());
myTree.getInputMap().clear();
TreeUtil.installActions(myTree);
@@ -88,8 +100,11 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myTree.setRootVisible(false);
myTree.setShowsRootHandles(false);
- myScroller = ScrollPaneFactory.createScrollPane(myTree);
- myScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ myScroller = ScrollPaneFactory.createScrollPane(myTree, true);
+ myScroller.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
+ myScroller.setBackground(UIUtil.getSidePanelColor());
+ myScroller.getViewport().setBackground(UIUtil.getSidePanelColor());
+ myScroller.getVerticalScrollBar().setBackground(UIUtil.getSidePanelColor());
add(myScroller);
myTree.addComponentListener(new ComponentAdapter() {
@@ -116,29 +131,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
});
- myTree.addKeyListener(new KeyListener() {
- public void keyTyped(KeyEvent event) {
- if (listener != null && isValid(event)) {
- listener.keyTyped(event);
- }
- }
-
- public void keyPressed(KeyEvent event) {
- if (listener != null && isValid(event)) {
- listener.keyPressed(event);
- }
- }
-
- public void keyReleased(KeyEvent event) {
- if (listener != null && isValid(event)) {
- listener.keyReleased(event);
- }
- }
-
- private boolean isValid(KeyEvent event) {
- return null == myTree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event));
- }
- });
myBuilder = new MyBuilder(new SimpleTreeStructure.Impl(myRoot));
myBuilder.setFilteringMerge(300, null);
Disposer.register(this, myBuilder);
@@ -158,9 +150,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
return ArrayUtil.toStringArray(path);
}
+ static Configurable getConfigurable(SimpleNode node) {
+ return node instanceof MyNode
+ ? ((MyNode)node).myConfigurable
+ : null;
+ }
+
@Nullable
- SimpleNode findNode(Configurable toSelect) {
- return myConfigurableToNodeMap.get(toSelect);
+ SimpleNode findNode(Configurable configurable) {
+ return myConfigurableToNodeMap.get(configurable);
}
@Nullable
@@ -250,24 +248,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
: null;
}
- static boolean isFiltered(Set<Configurable> configurables, ConfigurableHit hits, SimpleNode value) {
- if (value instanceof MyNode && !configurables.contains(((MyNode)value).myConfigurable)) {
- if (hits != null) {
- configurables = hits.getNameFullHits();
- while (value != null) {
- if (value instanceof MyNode) {
- if (configurables.contains(((MyNode)value).myConfigurable)) {
- return true;
- }
- }
- value = value.getParent();
- }
- }
- return false;
- }
- return true;
- }
-
@Override
public void doLayout() {
myScroller.setBounds(0, 0, getWidth(), getHeight());
@@ -277,34 +257,34 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
public void paint(Graphics g) {
super.paint(g);
+ if (0 == myTree.getY()) {
+ return; // separator is not needed without scrolling
+ }
if (mySeparator == null) {
mySeparator = new JLabel();
+ mySeparator.setForeground(NORMAL_NODE);
mySeparator.setFont(UIUtil.getLabelFont());
mySeparator.setFont(getFont().deriveFont(Font.BOLD));
}
- ConfigurableGroup group = findConfigurableGroupAt(0, 5 + mySeparator.getFont().getSize());
- if (group != null && group == findConfigurableGroupAt(0, -5)) {
- int offset = UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3;
- mySeparator.setBorder(BorderFactory.createEmptyBorder(offset, 18, offset, 3));
+ int height = mySeparator.getPreferredSize().height;
+ ConfigurableGroup group = findConfigurableGroupAt(0, height);
+ if (group != null && group == findConfigurableGroupAt(0, -myRenderer.getSeparatorHeight())) {
+ mySeparator.setBorder(BorderFactory.createEmptyBorder(0, 18, 0, 0));
mySeparator.setText(group.getDisplayName());
Rectangle bounds = myScroller.getViewport().getBounds();
- int height = mySeparator.getPreferredSize().height;
if (bounds.height > height) {
bounds.height = height;
}
g.setColor(myTree.getBackground());
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
if (g instanceof Graphics2D) {
- int h = bounds.height / 4;
- int y = bounds.y + bounds.height - h;
- g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height - h);
+ int h = 4; // gradient height
+ int y = bounds.y + bounds.height;
((Graphics2D)g).setPaint(UIUtil.getGradientPaint(
0, y, g.getColor(),
0, y + h, ColorUtil.toAlpha(g.getColor(), 0)));
- g.fillRect(bounds.x, y, bounds.width, h + h);
- }
- else {
- g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ g.fillRect(bounds.x, y, bounds.width, h);
}
mySeparator.setSize(bounds.width - 1, bounds.height);
mySeparator.paint(g.create(bounds.x + 1, bounds.y, bounds.width - 1, bounds.height));
@@ -373,7 +353,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
private void fireSelected(Configurable configurable, ActionCallback callback) {
- myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
+ myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
}
@Override
@@ -435,20 +415,21 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myConfigurable = configurable;
String name = configurable.getDisplayName();
myDisplayName = name != null ? name.replace("\n", " ") : "{ " + configurable.getClass().getSimpleName() + " }";
-
- myConfigurableToNodeMap.put(configurable, this);
}
private MyNode(CachingSimpleNode parent, ConfigurableGroup group) {
super(parent);
myComposite = group;
- myConfigurable = null;
+ myConfigurable = group instanceof Configurable ? (Configurable)group : null;
String name = group.getDisplayName();
myDisplayName = name != null ? name.replace("\n", " ") : "{ " + group.getClass().getSimpleName() + " }";
}
@Override
protected SimpleNode[] buildChildren() {
+ if (myConfigurable != null) {
+ myConfigurableToNodeMap.put(myConfigurable, this);
+ }
if (myComposite == null) {
return NO_CHILDREN;
}
@@ -460,7 +441,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
for (int i = 0; i < configurables.length; i++) {
result[i] = new MyNode(this, configurables[i]);
if (myConfigurable != null) {
- myContext.registerKid(myConfigurable, configurables[i]);
+ myFilter.myContext.registerKid(myConfigurable, configurables[i]);
}
}
return result;
@@ -470,11 +451,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
public boolean isAlwaysLeaf() {
return myComposite == null;
}
-
- @Override
- public int getWeight() {
- return WeightBasedComparator.UNDEFINED_WEIGHT;
- }
}
private final class MyRenderer extends GroupedElementsRenderer.Tree {
@@ -490,8 +466,9 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
protected void layout() {
myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
- myProjectIcon.setOpaque(true);
- myRendererComponent.add(BorderLayout.NORTH, mySeparatorComponent);
+ myNodeIcon.setOpaque(false);
+ myTextLabel.setOpaque(false);
+ myProjectIcon.setOpaque(false);
myRendererComponent.add(BorderLayout.CENTER, myComponent);
myRendererComponent.add(BorderLayout.WEST, myNodeIcon);
myRendererComponent.add(BorderLayout.EAST, myProjectIcon);
@@ -504,22 +481,17 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
boolean leaf,
int row,
boolean focused) {
- myTextLabel.setOpaque(selected);
myTextLabel.setFont(UIUtil.getLabelFont());
-
- String text;
- boolean hasSeparatorAbove = false;
- int preferredForcedWidth = -1;
+ myRendererComponent.setBackground(selected ? UIUtil.getTreeSelectionBackground() : myTree.getBackground());
MyNode node = extractNode(value);
if (node == null) {
- text = value.toString();
+ myTextLabel.setText(value.toString());
}
else {
- text = node.myDisplayName;
+ myTextLabel.setText(node.myDisplayName);
// show groups in bold
if (myRoot == node.getParent()) {
- hasSeparatorAbove = node != myRoot.getChildAt(0);
myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
}
TreePath path = tree.getPathForRow(row);
@@ -543,18 +515,18 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
forcedWidth = visibleRect.width > 0 ? visibleRect.width - indent : forcedWidth;
}
- preferredForcedWidth = forcedWidth - 4;
+ myRendererComponent.setPrefereedWidth(forcedWidth - 4);
}
- Component result = configureComponent(text, null, null, null, selected, hasSeparatorAbove, null, preferredForcedWidth);
// update font color for modified configurables
+ myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground() : NORMAL_NODE);
if (!selected && node != null) {
Configurable configurable = node.myConfigurable;
if (configurable != null) {
- if (myContext.getErrors().containsKey(configurable)) {
- myTextLabel.setForeground(JBColor.RED);
+ if (myFilter.myContext.getErrors().containsKey(configurable)) {
+ myTextLabel.setForeground(WRONG_CONTENT);
}
- else if (myContext.getModified().contains(configurable)) {
- myTextLabel.setForeground(JBColor.BLUE);
+ else if (myFilter.myContext.getModified().contains(configurable)) {
+ myTextLabel.setForeground(MODIFIED_CONTENT);
}
}
}
@@ -586,7 +558,6 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault()
? "configurable.default.project.tooltip"
: "configurable.current.project.tooltip"));
- myProjectIcon.setBackground(myTextLabel.getBackground());
myProjectIcon.setVisible(true);
}
else {
@@ -601,9 +572,12 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
else {
myNodeIcon.setIcon(null);
}
- return result;
+ return myRendererComponent;
}
+ int getSeparatorHeight() {
+ return mySeparatorComponent.getParent() == null ? 0 : mySeparatorComponent.getPreferredSize().height;
+ }
public boolean isUnderHandle(Point point) {
Point handlePoint = SwingUtilities.convertPoint(myRendererComponent, point, myNodeIcon);
@@ -720,7 +694,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
super.processMouseEvent(e);
}
- private final class MyTreeUi extends BasicTreeUI {
+ private final class MyTreeUi extends WideSelectionTreeUI {
@Override
public void toggleExpandState(TreePath path) {
@@ -773,7 +747,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
boolean myWasHoldingFilter;
public MyBuilder(SimpleTreeStructure structure) {
- super(myTree, myContext.getFilter(), structure, new WeightBasedComparator(false));
+ super(myTree, myFilter, structure, null);
myTree.addTreeExpansionListener(new TreeExpansionListener() {
public void treeExpanded(TreeExpansionEvent event) {
invalidateExpansions();
@@ -798,7 +772,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@Override
public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
- return myContext.isHoldingFilter();
+ return myFilter.myContext.isHoldingFilter();
}
@Override
@@ -809,22 +783,22 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@Override
protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) {
final List<Object> toRestore = new ArrayList<Object>();
- if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) {
+ if (myFilter.myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) {
myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements();
}
- else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) {
+ else if (!myFilter.myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) {
toRestore.addAll(myToExpandOnResetFilter);
myToExpandOnResetFilter = null;
}
- myWasHoldingFilter = myContext.isHoldingFilter();
+ myWasHoldingFilter = myFilter.myContext.isHoldingFilter();
ActionCallback result = super.refilterNow(preferredSelection, adjustSelection);
myRefilteringNow = true;
return result.doWhenDone(new Runnable() {
public void run() {
myRefilteringNow = false;
- if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) {
+ if (!myFilter.myContext.isHoldingFilter() && getSelectedElements().isEmpty()) {
restoreExpandedState(toRestore);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
index 6a37bb2fb69e..3d478f2b7084 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
@@ -47,6 +47,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class ProgressManagerImpl extends ProgressManager implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl");
+ public static final int CHECK_CANCELED_DELAY_MILLIS = 10;
private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0);
private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0);
@@ -64,7 +65,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable {
public void run() {
ourNeedToCheckCancel = true;
}
- }, 0, 10, TimeUnit.MILLISECONDS);
+ }, 0, CHECK_CANCELED_DELAY_MILLIS, TimeUnit.MILLISECONDS);
}
}
@@ -83,7 +84,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable {
ourLockedCheckCounter++;
if (ourLockedCheckCounter > 10) {
ourLockedCheckCounter = 0;
- ourNeedToCheckCancel = true;
+ canceled();
}
}
else {
@@ -94,10 +95,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable {
}
}
- public static void canceled() {
- ourNeedToCheckCancel = true;
- }
-
private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection {
private final ProgressIndicator myOld;
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java
index 2d9a7b3a88e6..b4821f52fddb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 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.
@@ -19,7 +19,6 @@ import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.TaskInfo;
-import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.WeakList;
@@ -151,9 +150,6 @@ public class ProgressIndicatorBase extends AbstractProgressIndicatorBase impleme
@Override
public void cancel() {
super.cancel();
-
- ProgressManagerImpl.canceled();
-
delegateRunningChange(CANCEL_ACTION);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
index 0c18cb7706d9..368200492cae 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
@@ -22,7 +22,11 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.ui.AppUIUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.ide.PooledThreadExecutor;
+
+import java.util.concurrent.Executor;
/**
* @author gregsh
@@ -44,96 +48,76 @@ public class ProgressIndicatorUtils {
return progress;
}
- public static void runWithWriteActionPriority(@NotNull final Runnable action) {
- runWithWriteActionPriority(new ReadTask() {
- @Override
- public void computeInReadAction(@NotNull ProgressIndicator indicator) {
- action.run();
- }
-
- @Override
- public void onCanceled(@NotNull ProgressIndicator indicator) {
- }
- });
- }
-
- public static void runWithWriteActionPriority(@NotNull final ReadTask task) {
- runWithWriteActionPriority(new ProgressIndicatorBase(), task);
+ public static void scheduleWithWriteActionPriority(@NotNull ReadTask task) {
+ scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
}
- private static void surroundWithListener(@NotNull final ProgressIndicator progressIndicator, @NotNull Runnable runnable) {
- final ApplicationAdapter listener = new ApplicationAdapter() {
- @Override
- public void beforeWriteActionStart(Object action) {
- progressIndicator.cancel();
- }
- };
- final Application application = ApplicationManager.getApplication();
- application.addApplicationListener(listener);
- try {
- runnable.run();
- }
- finally {
- application.removeApplicationListener(listener);
- }
+ public static void scheduleWithWriteActionPriority(@NotNull ProgressIndicator progressIndicator, @NotNull ReadTask readTask) {
+ scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
}
-
- public static void runWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
- surroundWithListener(progressIndicator, new Runnable() {
+ public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
+ @NotNull final Executor executor,
+ @NotNull final ReadTask readTask) {
+ AppUIUtil.invokeOnEdt(new Runnable() {
@Override
public void run() {
- runUnderProgress(progressIndicator, task);
+ final Application application = ApplicationManager.getApplication();
+ application.assertIsDispatchThread();
+ final ApplicationAdapter listener = new ApplicationAdapter() {
+ @Override
+ public void beforeWriteActionStart(Object action) {
+ progressIndicator.cancel();
+ }
+ };
+ application.addApplicationListener(listener);
+ try {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ runUnderProgress(progressIndicator, readTask);
+ }
+ finally {
+ application.removeApplicationListener(listener);
+ }
+ }
+ });
+ }
+ catch (RuntimeException e) {
+ application.removeApplicationListener(listener);
+ throw e;
+ }
+ catch (Error e) {
+ application.removeApplicationListener(listener);
+ throw e;
+ }
}
});
}
private static void runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
ProgressManager.getInstance().runProcess(new Runnable() {
- @Override
- public void run() {
- // This read action can possible last for a long time, we want it to stop immediately on the first write access.
- // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
- try {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- task.computeInReadAction(progressIndicator);
- }
- });
- }
- catch (ProcessCanceledException ignore) {
- }
- finally {
- if (progressIndicator.isCanceled()) {
- task.onCanceled(progressIndicator);
- }
- }
- }
- }, progressIndicator);
- }
-
- public static void scheduleWithWriteActionPriority(@NotNull final ReadTask task) {
- scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
- }
-
- public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator indicator, @NotNull final ReadTask task) {
- // we have to attach listeners in EDT to avoid "fire write action started while attach listeners from another thread" race condition
- ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- surroundWithListener(indicator, new Runnable() {
- @Override
- public void run() {
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
- @Override
- public void run() {
- runUnderProgress(indicator, task);
- }
- });
+ // This read action can possible last for a long time, we want it to stop immediately on the first write access.
+ // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
+ try {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ task.computeInReadAction(progressIndicator);
+ }
+ });
+ }
+ catch (ProcessCanceledException ignore) {
+ }
+ finally {
+ if (progressIndicator.isCanceled()) {
+ task.onCanceled(progressIndicator);
}
- });
+ }
}
- });
+ }, progressIndicator);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectMacrosUtil.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectMacrosUtil.java
index 77baf2a6b98c..1f3b9d149ccc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectMacrosUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectMacrosUtil.java
@@ -25,17 +25,13 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathMacros;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.options.ex.SingleConfigurableEditor;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.WaitForProgressToShow;
import org.jetbrains.annotations.NonNls;
-import javax.swing.*;
-import java.lang.reflect.InvocationTargetException;
import java.util.*;
public class ProjectMacrosUtil {
@@ -50,11 +46,7 @@ public class ProjectMacrosUtil {
if (application.isHeadlessEnvironment() || application.isUnitTestMode()) {
throw new RuntimeException(text + ": " + StringUtil.join(undefinedMacros, ", "));
}
- final UndefinedMacrosConfigurable configurable =
- new UndefinedMacrosConfigurable(text, undefinedMacros);
- final SingleConfigurableEditor editor = new SingleConfigurableEditor(project, configurable);
- editor.show();
- return editor.isOK();
+ return ShowSettingsUtil.getInstance().editConfigurable(project, new UndefinedMacrosConfigurable(text, undefinedMacros));
}
public static boolean checkNonIgnoredMacros(final Project project, final Set<String> usedMacros){
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
index 2f95c21cb558..e7b20959369e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
@@ -21,6 +21,7 @@ import com.intellij.conversion.ConversionService;
import com.intellij.ide.AppLifecycleListener;
import com.intellij.ide.RecentProjectsManagerBase;
import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.Disposable;
@@ -354,7 +355,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
myDefaultProjectRootElement = null;
}
catch (Throwable t) {
- LOG.error(t);
+ PluginManager.processException(t);
}
}
});
@@ -362,6 +363,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
return myDefaultProject;
}
+ @Nullable
public Element getDefaultProjectRootElement() {
return myDefaultProjectRootElement;
}
@@ -1126,33 +1128,27 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
}
@Override
- public void writeExternal(Element parentNode) throws WriteExternalException {
+ public void writeExternal(Element parentNode) {
if (myDefaultProject != null) {
myDefaultProject.save();
}
- if (myDefaultProjectRootElement == null) { //read external isn't called if config folder is absent
- myDefaultProjectRootElement = new Element(ELEMENT_DEFAULT_PROJECT);
+ if (myDefaultProjectRootElement != null) {
+ myDefaultProjectRootElement.detach();
+ parentNode.addContent(myDefaultProjectRootElement);
}
-
- myDefaultProjectRootElement.detach();
- parentNode.addContent(myDefaultProjectRootElement);
}
-
public void setDefaultProjectRootElement(final Element defaultProjectRootElement) {
myDefaultProjectRootElement = defaultProjectRootElement;
}
@Override
- public void readExternal(Element parentNode) throws InvalidDataException {
+ public void readExternal(Element parentNode) {
myDefaultProjectRootElement = parentNode.getChild(ELEMENT_DEFAULT_PROJECT);
-
- if (myDefaultProjectRootElement == null) {
- myDefaultProjectRootElement = new Element(ELEMENT_DEFAULT_PROJECT);
+ if (myDefaultProjectRootElement != null) {
+ myDefaultProjectRootElement.detach();
}
-
- myDefaultProjectRootElement.detach();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
index 394dec20f4ef..1160c64bbeb8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
@@ -15,7 +15,8 @@
*/
package com.intellij.openapi.updateSettings.impl.pluginsAdvertisement;
-import com.intellij.ide.plugins.*;
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.RepositoryHelper;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileTypes.FileTypeFactory;
@@ -24,7 +25,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.updateSettings.impl.*;
+import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
@@ -94,7 +95,8 @@ public class PluginAdvertiserEditorNotificationProvider extends EditorNotificati
@Nullable
private EditorNotificationPanel createPanel(final String extension, final Set<PluginsAdvertiser.Plugin> plugins) {
final EditorNotificationPanel panel = new EditorNotificationPanel();
- panel.setText("Plugins supporting files with " + extension + " are found");
+
+ panel.setText("Plugins supporting " + extension + " files are found");
final IdeaPluginDescriptor disabledPlugin = PluginsAdvertiser.getDisabledPlugin(plugins);
if (disabledPlugin != null) {
panel.createActionLabel("Enable " + disabledPlugin.getName() + " plugin", new Runnable() {
@@ -143,6 +145,7 @@ public class PluginAdvertiserEditorNotificationProvider extends EditorNotificati
if (PropertiesComponent.getInstance().isTrueValue(PluginsAdvertiser.IGNORE_ULTIMATE_EDITION)) {
return null;
}
+ panel.setText(extension + " files are supported by " + PluginsAdvertiser.IDEA_ULTIMATE_EDITION);
panel.createActionLabel(PluginsAdvertiser.CHECK_ULTIMATE_EDITION_TITLE, new Runnable() {
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
index ed6a629bff0d..4ae3caee88e1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java
@@ -63,8 +63,9 @@ public class PluginsAdvertiser implements StartupActivity {
private static final String FEATURE_IMPLEMENTATIONS_URL = "http://plugins.jetbrains.com/feature/getImplementations?";
private static final String CASHED_EXTENSIONS = "extensions.xml";
+ public static final String IDEA_ULTIMATE_EDITION = "IntelliJ IDEA Ultimate Edition";
public static final String ULTIMATE_EDITION_SUGGESTION = "Do not suggest Ultimate Edition";
- public static final String CHECK_ULTIMATE_EDITION_TITLE = "Check IntelliJ IDEA Ultimate Edition";
+ public static final String CHECK_ULTIMATE_EDITION_TITLE = "Check " + IDEA_ULTIMATE_EDITION;
public static final String DISPLAY_ID = "Plugins Suggestion";
public static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup(DISPLAY_ID, NotificationDisplayType.STICKY_BALLOON, true);
@@ -198,7 +199,7 @@ public class PluginsAdvertiser implements StartupActivity {
}
public static void openDownloadPage() {
- BrowserUtil.open(ApplicationInfo.getInstance().getCompanyURL());
+ BrowserUtil.browse(ApplicationInfo.getInstance().getCompanyURL());
}
static void enablePlugins(Project project, final Collection<IdeaPluginDescriptor> disabledPlugins) {
@@ -325,7 +326,8 @@ public class PluginsAdvertiser implements StartupActivity {
message += "<a href=\"ignore\">Ignore All</a>";
}
else if (myBundledPlugin != null && !PropertiesComponent.getInstance().isTrueValue(IGNORE_ULTIMATE_EDITION)) {
- message = "Features covered by IntelliJ IDEA Ultimate Edition (" + StringUtil.join(myBundledPlugin, ", ") + ") are detected.<br>" +
+ message = "Features covered by " + IDEA_ULTIMATE_EDITION +
+ " (" + StringUtil.join(myBundledPlugin, ", ") + ") are detected.<br>" +
"<a href=\"open\">" + CHECK_ULTIMATE_EDITION_TITLE + "</a><br>" +
"<a href=\"ignoreUltimate\">" + ULTIMATE_EDITION_SUGGESTION + "</a>";
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
index 402d88cef38a..92eed9582fd2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
@@ -27,18 +27,24 @@ import java.awt.event.MouseMotionListener;
public abstract class LinkMouseListenerBase<T> extends ClickListener implements MouseMotionListener {
public static void installSingleTagOn(@NotNull SimpleColoredComponent component) {
- new LinkMouseListenerBase<Consumer<MouseEvent>>() {
+ new LinkMouseListenerBase<Object>() {
@Nullable
@Override
- protected Consumer<MouseEvent> getTagAt(@NotNull MouseEvent e) {
+ protected Object getTagAt(@NotNull MouseEvent e) {
//noinspection unchecked
- return (Consumer<MouseEvent>)((SimpleColoredComponent)e.getSource()).getFragmentTagAt(e.getX());
+ return ((SimpleColoredComponent)e.getSource()).getFragmentTagAt(e.getX());
}
@Override
- protected void handleTagClick(@Nullable Consumer<MouseEvent> tag, @NotNull MouseEvent event) {
+ protected void handleTagClick(@Nullable Object tag, @NotNull MouseEvent event) {
if (tag != null) {
- tag.consume(event);
+ if (tag instanceof Consumer) {
+ //noinspection unchecked
+ ((Consumer<MouseEvent>)tag).consume(event);
+ }
+ else {
+ ((Runnable)tag).run();
+ }
}
}
}.installOn(component);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
index 1c6e173b45d1..33ecf625c05d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
@@ -136,7 +136,8 @@ public class TempFileSystem extends LocalFileSystemBase {
}
fsItem.getParent().removeChild(fsItem);
- ((FSDir)newParentItem).addChild(fsItem);
+ newDir.addChild(fsItem);
+ fsItem.myParent = newDir;
}
@Override
@@ -263,7 +264,7 @@ public class TempFileSystem extends LocalFileSystemBase {
}
private abstract static class FSItem {
- private final FSDir myParent;
+ private FSDir myParent;
private String myName;
private long myTimestamp;
private boolean myWritable;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
index d7b90178e7e8..db5de4258d41 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
@@ -67,15 +67,16 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
private final Object myInputLock = new Object();
private final AtomicBoolean myShutDown = new AtomicBoolean(false);
+ @SuppressWarnings("FieldCanBeLocal")
+ private final LowMemoryWatcher myWatcher = LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ clearIdCache();
+ }
+ });
public PersistentFSImpl(@NotNull MessageBus bus) {
myEventBus = bus;
- LowMemoryWatcher.register(new Runnable() {
- @Override
- public void run() {
- clearIdCache();
- }
- });
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
@Override
public void run() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.form b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.form
index 2e1bb768a614..4e362a30a1ed 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.form
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.form
@@ -22,7 +22,7 @@
</constraints>
<properties>
<autoscrolls value="true"/>
- <text value="Text"/>
+ <text value=""/>
</properties>
</component>
<component id="94f42" class="javax.swing.JProgressBar" binding="myProgressBar" default-binding="true">
@@ -54,7 +54,7 @@
</grid>
</constraints>
<properties>
- <text value="Text 2"/>
+ <text value=""/>
</properties>
</component>
<vspacer id="8e674">
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.java
index d7bc7024f0ed..9f82a2f60cdf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PresentationModeProgressPanel.java
@@ -22,6 +22,7 @@ import com.intellij.ui.InplaceButton;
import com.intellij.ui.TransparentPanel;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -69,7 +70,7 @@ public class PresentationModeProgressPanel {
}
if (!myProgressBar.isIndeterminate()) {
- myProgressBar.setValue(((int)(myProgress.getFraction() * 99)) + 1);
+ myProgressBar.setValue((int)(myProgress.getFraction() * 99) + 1);
}
}
@@ -83,7 +84,7 @@ public class PresentationModeProgressPanel {
AllIcons.Process.Stop,
AllIcons.Process.StopHovered);
myCancelButton = new InplaceButton(iconButton, new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
+ public void actionPerformed(@NotNull final ActionEvent e) {
myProgress.cancel();
}
}).setFillBg(false);
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index 1fc23e5f4055..d9ebeefa7acc 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -368,6 +368,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
if (!(renderer instanceof JComponent)) return null;
myKeyItemBounds = rendererAndBounds.second;
+ myKeyItemBounds.width = Math.min(myKeyItemBounds.width, myComponent.getToolkit().getScreenSize().width);
Rectangle cellBounds = myKeyItemBounds;
Rectangle visibleRect = getVisibleRect(key);
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index 2a7d44d017bd..f4bf768e92a6 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
@@ -90,19 +90,19 @@ public class AppUIUtil {
invokeOnEdt(runnable, null);
}
- public static void invokeOnEdt(Runnable runnable, @Nullable Condition condition) {
+ public static void invokeOnEdt(Runnable runnable, @Nullable Condition expired) {
Application application = ApplicationManager.getApplication();
if (application.isDispatchThread()) {
//noinspection unchecked
- if (condition == null || !condition.value(null)) {
+ if (expired == null || !expired.value(null)) {
runnable.run();
}
}
- else if (condition == null) {
+ else if (expired == null) {
application.invokeLater(runnable);
}
else {
- application.invokeLater(runnable, condition);
+ application.invokeLater(runnable, expired);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
index f4dfb1059651..60371365f2c3 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
@@ -17,6 +17,7 @@ package com.intellij.ui;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
@@ -34,10 +35,19 @@ public class EditorComboBoxEditor implements ComboBoxEditor{
@NonNls protected static final String NAME = "ComboBox.textField";
public EditorComboBoxEditor(Project project, FileType fileType) {
- myTextField = new ComboboxEditorTextField((Document)null, project, fileType);
+ myTextField = new ComboboxEditorTextField((Document)null, project, fileType) {
+ @Override
+ protected EditorEx createEditor() {
+ EditorEx editor = super.createEditor();
+ onEditorCreate(editor);
+ return editor;
+ }
+ };
myTextField.setName(NAME);
}
+ protected void onEditorCreate(EditorEx editor) {}
+
@Override
public void selectAll() {
myTextField.selectAll();
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java
index 5721f4af4821..4b788c80ae54 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorNotificationsImpl.java
@@ -102,13 +102,7 @@ public class EditorNotificationsImpl extends EditorNotifications {
task.computeInReadAction(indicator);
}
else {
- final ProgressIndicator indicator1 = indicator;
- myExecutor.execute(new Runnable() {
- @Override
- public void run() {
- ProgressIndicatorUtils.runWithWriteActionPriority(indicator1, task);
- }
- });
+ ProgressIndicatorUtils.scheduleWithWriteActionPriority(indicator, myExecutor, task);
}
}
});
@@ -165,7 +159,7 @@ public class EditorNotificationsImpl extends EditorNotifications {
}
@Override
- public void onCanceled(@NotNull ProgressIndicator _) {
+ public void onCanceled(@NotNull ProgressIndicator ignored) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
index c16f5f188cdc..27b1a2be56ae 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
@@ -278,13 +278,18 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
public void selectAll() {
if (myEditor != null) {
- myEditor.getSelectionModel().setSelection(0, myDocument.getTextLength());
+ doSelectAll(myEditor);
}
else {
myWholeTextSelected = true;
}
}
+ private static void doSelectAll(@NotNull Editor editor) {
+ editor.getCaretModel().removeSecondaryCarets();
+ editor.getCaretModel().getPrimaryCaret().setSelection(0, editor.getDocument().getTextLength(), false);
+ }
+
public void removeSelection() {
if (myEditor != null) {
myEditor.getSelectionModel().removeSelection();
@@ -514,7 +519,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener,
editor.getSelectionModel().removeSelection();
}
else if (myWholeTextSelected) {
- editor.getSelectionModel().setSelection(0, myDocument.getTextLength());
+ doSelectAll(editor);
+ myWholeTextSelected = false;
}
editor.putUserData(SUPPLEMENTARY_KEY, myIsSupplementary);
diff --git a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java
index 9ad0931c85b9..5c531a7b6ae8 100644
--- a/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java
+++ b/platform/platform-impl/src/com/intellij/ui/FocusTrackback.java
@@ -191,10 +191,12 @@ public class FocusTrackback {
if (app == null || wrongOS() || myConsumed || isSheduledForRestore()) return;
Project project = null;
- DataContext context =
- myParentWindow == null ? DataManager.getInstance().getDataContext() : DataManager.getInstance().getDataContext(myParentWindow);
- if (context != null) {
- project = CommonDataKeys.PROJECT.getData(context);
+ DataManager dataManager = DataManager.getInstance();
+ if (dataManager != null) {
+ DataContext context = myParentWindow == null ? dataManager.getDataContext() : dataManager.getDataContext(myParentWindow);
+ if (context != null) {
+ project = CommonDataKeys.PROJECT.getData(context);
+ }
}
mySheduledForRestore = true;
diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
index e8c6f49f8088..7e613982a406 100644
--- a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
+++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
@@ -50,6 +50,8 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier {
private final LibNotify myLibNotify;
private final String myIcon;
+ private final Object myLock = new Object();
+ private boolean myDisposed = false;
private LibNotifyWrapper() {
myLibNotify = (LibNotify)Native.loadLibrary("libnotify.so.4", LibNotify.class);
@@ -66,14 +68,21 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier {
connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
@Override
public void appClosing() {
- myLibNotify.notify_uninit();
+ synchronized (myLock) {
+ myDisposed = true;
+ myLibNotify.notify_uninit();
+ }
}
});
}
@Override
public void notify(@NotNull Set<String> allNames, @NotNull String name, @NotNull String title, @NotNull String description) {
- Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon);
- myLibNotify.notify_notification_show(notification, null);
+ synchronized (myLock) {
+ if (!myDisposed) {
+ Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon);
+ myLibNotify.notify_notification_show(notification, null);
+ }
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
index cbcde2d36418..76985ad77362 100644
--- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
+++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
@@ -298,6 +298,7 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
protected void processKeyEvent(KeyEvent e) {
if (e.isAltDown()) return;
+ if (e.isShiftDown() && isNavigationKey(e.getKeyCode())) return;
if (mySearchPopup != null) {
mySearchPopup.processKeyEvent(e);
return;
@@ -499,6 +500,15 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
return keyCode == KeyEvent.VK_HOME || keyCode == KeyEvent.VK_END || keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN;
}
+ private static boolean isPgUpPgDown(int keyCode) {
+ return keyCode == KeyEvent.VK_PAGE_UP || keyCode == KeyEvent.VK_PAGE_DOWN;
+ }
+
+ private static boolean isNavigationKey(int keyCode) {
+ return isPgUpPgDown(keyCode) || isUpDownHomeEnd(keyCode);
+ }
+
+
private void manageSearchPopup(@Nullable SearchPopup searchPopup) {
Project project = null;
if (ApplicationManager.getApplication() != null && !ApplicationManager.getApplication().isDisposed()) {
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
index 2d76d6391ee8..bf0b37116941 100755
--- a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
@@ -70,6 +70,8 @@ public class SheetController {
private static int GAP_BETWEEN_BUTTONS = 5;
+ private static String SPACE_OR_LINE_SEPARATOR_PATTERN = "[\\s" + System.getProperty("line.separator") + "]+";
+
// SHEET
public int SHEET_WIDTH = 400;
@@ -289,7 +291,7 @@ public class SheetController {
int widestWordWidth = 250;
- String [] words = (message == null) ? ArrayUtil.EMPTY_STRING_ARRAY : message.split(" ");
+ String [] words = (message == null) ? ArrayUtil.EMPTY_STRING_ARRAY : message.split(SPACE_OR_LINE_SEPARATOR_PATTERN);
for (String word : words) {
widestWordWidth = Math.max(fontMetrics.stringWidth(word), widestWordWidth);
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
index 446722c081e4..fee84330f0a2 100755
--- a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
@@ -70,6 +70,8 @@ public class SheetMessage {
final Component recentFocusOwner = activeWindow == null ? null : activeWindow.getMostRecentFocusOwner();
beforeShowFocusOwner = new WeakReference<Component>(recentFocusOwner);
+ maximizeIfNeeded(owner);
+
myWindow = new JDialog(owner, "This should not be shown", Dialog.ModalityType.APPLICATION_MODAL);
myWindow.getRootPane().putClientProperty("apple.awt.draggableWindowBackground", Boolean.FALSE);
@@ -132,6 +134,16 @@ public class SheetMessage {
}
+ private static void maximizeIfNeeded(final Window owner) {
+ if (owner == null) return;
+ if (owner instanceof Frame) {
+ Frame f = (Frame)owner;
+ if (f.getState() == Frame.ICONIFIED) {
+ f.setState(Frame.NORMAL);
+ }
+ }
+ }
+
private void setWindowOpacity(float opacity) {
try {
Method setOpacityMethod = myWindow.getClass().getMethod("setOpacity", Float.TYPE);
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
index 04c38a6cc295..1b9190f6a740 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
@@ -177,15 +177,19 @@ public abstract class WizardPopup extends AbstractPopup implements ActionListene
LOG.assertTrue (!isDisposed());
Rectangle targetBounds = new Rectangle(new Point(aScreenX, aScreenY), getContent().getPreferredSize());
- ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
if (getParent() != null) {
final Rectangle parentBounds = getParent().getBounds();
parentBounds.x += STEP_X_PADDING;
parentBounds.width -= STEP_X_PADDING * 2;
+ ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(
+ parentBounds.x + parentBounds.width / 2,
+ parentBounds.y + parentBounds.height / 2), null);
if (parentBounds.intersects(targetBounds)) {
targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING;
}
+ } else {
+ ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(aScreenX, aScreenY), null);
}
if (getParent() == null) {