summaryrefslogtreecommitdiff
path: root/platform/platform-impl/src/com/intellij
diff options
context:
space:
mode:
Diffstat (limited to 'platform/platform-impl/src/com/intellij')
-rw-r--r--platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java127
-rw-r--r--platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java30
-rw-r--r--platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java4
-rw-r--r--platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java20
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java22
-rw-r--r--platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java14
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java40
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java14
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java9
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java25
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/Switcher.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java11
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java62
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java37
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java21
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java28
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java13
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java23
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties7
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java81
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java208
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java85
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java611
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java692
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java29
-rw-r--r--platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java36
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java61
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java31
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java58
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java56
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java68
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java23
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java113
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java27
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java76
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java150
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java11
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java33
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java132
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java67
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java323
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java (renamed from platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java)19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java8
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java27
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java18
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java46
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java52
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java62
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java17
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java18
-rwxr-xr-xplatform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java (renamed from platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java)9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java22
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java16
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java18
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java408
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java36
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java9
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java21
-rw-r--r--platform/platform-impl/src/com/intellij/remote/VagrantSupport.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AppUIUtil.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ui/BalloonImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ui/CheckboxTree.java9
-rw-r--r--platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java47
-rw-r--r--platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java45
-rw-r--r--platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java7
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java68
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java35
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java9
-rw-r--r--platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java92
103 files changed, 3399 insertions, 1458 deletions
diff --git a/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
new file mode 100644
index 000000000000..7d972816769c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
@@ -0,0 +1,127 @@
+/*
+ * 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.codeInsight.editorActions;
+
+import com.intellij.openapi.editor.RawText;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class TextBlockTransferable implements Transferable {
+ private final Collection<TextBlockTransferableData> myExtraData;
+ private final RawText myRawText;
+ private final String myText;
+ private final DataFlavor[] myTransferDataFlavors;
+
+ public TextBlockTransferable(String text, Collection<TextBlockTransferableData> extraData, RawText rawText) {
+ myText = text;
+ myExtraData = extraData;
+ myRawText = rawText;
+
+ List<DataFlavor> dataFlavors = new ArrayList<DataFlavor>();
+ Collections.addAll(dataFlavors, DataFlavor.stringFlavor, DataFlavor.plainTextFlavor);
+ final DataFlavor flavor = RawText.getDataFlavor();
+ if (myRawText != null && flavor != null) {
+ dataFlavors.add(flavor);
+ }
+ for(TextBlockTransferableData data: extraData) {
+ final DataFlavor blockFlavor = data.getFlavor();
+ if (blockFlavor != null) {
+ dataFlavors.add(blockFlavor);
+ }
+ }
+ myTransferDataFlavors = dataFlavors.toArray(new DataFlavor[dataFlavors.size()]);
+ }
+
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return myTransferDataFlavors;
+ }
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ DataFlavor[] flavors = getTransferDataFlavors();
+ for (DataFlavor flavor1 : flavors) {
+ if (flavor.equals(flavor1)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ try {
+ for(TextBlockTransferableData data: myExtraData) {
+ if (Comparing.equal(data.getFlavor(), flavor)) {
+ return data;
+ }
+ }
+ if (myRawText != null && Comparing.equal(RawText.getDataFlavor(), flavor)) {
+ return myRawText;
+ }
+ else if (DataFlavor.stringFlavor.equals(flavor)) {
+ return myText;
+ }
+ else if (DataFlavor.plainTextFlavor.equals(flavor)) {
+ return new StringReader(myText);
+ }
+ }
+ catch(NoClassDefFoundError e) {
+ // ignore
+ }
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+ public static String convertLineSeparators(String text,
+ String newSeparator,
+ Collection<TextBlockTransferableData> transferableDatas) {
+ if (transferableDatas.size() > 0){
+ int size = 0;
+ for(TextBlockTransferableData data: transferableDatas) {
+ size += data.getOffsetCount();
+ }
+
+ int[] offsets = new int[size];
+ int index = 0;
+ for(TextBlockTransferableData data: transferableDatas) {
+ index = data.getOffsets(offsets, index);
+ }
+
+ text = StringUtil.convertLineSeparators(text, newSeparator, offsets);
+
+ index = 0;
+ for(TextBlockTransferableData data: transferableDatas) {
+ index = data.setOffsets(offsets, index);
+ }
+
+ return text;
+ }
+ else{
+ return StringUtil.convertLineSeparators(text, newSeparator);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
new file mode 100644
index 000000000000..bdaf6f2ea546
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
@@ -0,0 +1,30 @@
+/*
+ * 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.codeInsight.editorActions;
+
+import java.awt.datatransfer.DataFlavor;
+
+/**
+ * @author yole
+ */
+public interface TextBlockTransferableData {
+ DataFlavor getFlavor();
+
+ int getOffsetCount();
+ int getOffsets(final int[] offsets, final int index);
+ int setOffsets(final int[] offsets, final int index);
+}
diff --git a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
index 64aefa4c0977..b8e17ea3eded 100644
--- a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
+++ b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.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.
@@ -115,7 +115,7 @@ public class DelayedDocumentWatcher {
public void documentChanged(DocumentEvent event) {
if (myDocumentSavingInProgress) {
/** When {@link FileDocumentManager#saveAllDocuments} is called,
- * {@link com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper} can change a document.
+ * {@link com.intellij.openapi.editor.impl.TrailingSpacesStripper} can change a document.
* These needless 'documentChanged' events should be filtered out.
*/
return;
diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
index 90d633f0d621..a73295c90f74 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
@@ -41,7 +41,7 @@ public class MacHelpUtil {
}
static boolean isApplicable() {
- return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils
+ return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils
.isIdeaCommunity();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
index 1bbd74984fcc..c8699c083ef4 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -952,25 +952,18 @@ public class IdeEventQueue extends EventQueue {
}
private static class WindowsAltSupressor implements EventDispatcher {
-
- private boolean myPureAltWasPressed;
private boolean myWaitingForAltRelease;
- private boolean myWaiterScheduled;
-
private Robot myRobot;
@Override
public boolean dispatch(AWTEvent e) {
boolean dispatch = true;
- if (!Registry.is("actionSystem.win.suppressAlt.new") && e instanceof KeyEvent) {
+ if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)e;
final Component component = ke.getComponent();
- final Window window = component == null ? null : SwingUtilities.windowForComponent(component);
boolean pureAlt = ke.getKeyCode() == KeyEvent.VK_ALT && (ke.getModifiers() | InputEvent.ALT_MASK) == InputEvent.ALT_MASK;
if (!pureAlt) {
- myPureAltWasPressed = false;
myWaitingForAltRelease = false;
- myWaiterScheduled = false;
}
else {
if (ApplicationManager.getApplication() == null ||
@@ -978,28 +971,25 @@ public class IdeEventQueue extends EventQueue {
!SystemInfo.isWindows ||
!Registry.is("actionSystem.win.suppressAlt") ||
!(UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE)) {
- return !dispatch;
+ return true;
}
if (ke.getID() == KeyEvent.KEY_PRESSED) {
- myPureAltWasPressed = true;
dispatch = !myWaitingForAltRelease;
}
else if (ke.getID() == KeyEvent.KEY_RELEASED) {
if (myWaitingForAltRelease) {
- myPureAltWasPressed = false;
myWaitingForAltRelease = false;
- myWaiterScheduled = false;
dispatch = false;
}
- else {
- myWaiterScheduled = true;
+ else if (component != null) {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
- if (SystemInfo.isWindows || window == null || !window.isActive()) {
+ final Window window = component instanceof Window ? (Window)component : SwingUtilities.windowForComponent(component);
+ if (window == null || !window.isActive()) {
return;
}
myWaitingForAltRelease = true;
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
index 8aa0e38c0d0d..d7118949e5de 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.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.
@@ -24,13 +24,12 @@ package com.intellij.ide;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.reference.SoftReference;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.image.VolatileImage;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
import java.util.Map;
/**
@@ -40,7 +39,6 @@ public class IdeRepaintManager extends RepaintManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.HackyRepaintManager");
private Map<GraphicsConfiguration, VolatileImage> myImagesMap;
- @NonNls private static final String FAULTY_FIELD_NAME = "volatileMap";
WeakReference<JComponent> myLastComponent;
@@ -53,14 +51,7 @@ public class IdeRepaintManager extends RepaintManager {
// sync here is to avoid data race when two(!) AWT threads on startup try to compete for the single myImagesMap
private synchronized void clearLeakyImages(boolean force) {
if (myImagesMap == null) {
- try {
- Field volMapField = RepaintManager.class.getDeclaredField(FAULTY_FIELD_NAME);
- volMapField.setAccessible(true);
- myImagesMap = (Map<GraphicsConfiguration, VolatileImage>)volMapField.get(this);
- }
- catch (Exception e) {
- LOG.error(e);
- }
+ myImagesMap = ReflectionUtil.getField(RepaintManager.class, this, Map.class, "volatileMap");
}
if (force ||
@@ -90,12 +81,12 @@ public class IdeRepaintManager extends RepaintManager {
// We must keep a strong reference to the DisplayChangedListener,
// since SunDisplayChanger keeps only a WeakReference to it.
- private Object displayChangeHack;
+ private DisplayChangeHandler displayChangeHack;
{
try {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice[] devices = env.getScreenDevices(); // init
+ env.getScreenDevices(); // init
Class<?> aClass = Class.forName("sun.awt.DisplayChangedListener"); // might be absent
displayChangeHack = new DisplayChangeHandler();
@@ -104,7 +95,8 @@ public class IdeRepaintManager extends RepaintManager {
.getMethod("addDisplayChangedListener", new Class[]{aClass})
.invoke(env, displayChangeHack);
}
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
if (!(t instanceof HeadlessException)) LOG.error("Cannot setup display change listener", t);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
index e3e1945d14f1..3b8bacee5457 100644
--- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
@@ -59,7 +59,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
static final class XmlRpcRequestHandler extends HttpRequestHandler {
@Override
public boolean isSupported(@NotNull FullHttpRequest request) {
- return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS;
+ return request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS;
}
@Override
@@ -89,7 +89,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
return false;
}
- if (request.getMethod() == HttpMethod.POST) {
+ if (request.method() == HttpMethod.POST) {
ByteBuf result;
ByteBufInputStream in = new ByteBufInputStream(request.content());
try {
@@ -116,7 +116,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
return true;
}
else if (HttpMethod.POST.name().equals(request.headers().get("Access-Control-Request-Method"))) {
- LOG.assertTrue(request.getMethod() == HttpMethod.OPTIONS);
+ LOG.assertTrue(request.method() == HttpMethod.OPTIONS);
Responses.sendOptionsResponse("POST, OPTIONS", request, context);
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
index 7bbc3e0c6cba..006830479db3 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
@@ -33,6 +33,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.FieldPanel;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,15 +56,14 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
private final boolean myShowFilePath;
private final String myDescription;
- public ChooseComponentsToExportDialog(List<ExportableComponent> components,
- Map<File, Set<ExportableComponent>> fileToComponents,
+ public ChooseComponentsToExportDialog(MultiMap<File, ExportableComponent> fileToComponents,
boolean showFilePath, final String title, String description) {
super(false);
myDescription = description;
myShowFilePath = showFilePath;
Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement = new LinkedHashMap<ExportableComponent, ComponentElementProperties>();
- for (ExportableComponent component : components) {
+ for (ExportableComponent component : fileToComponents.values()) {
if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) {
ComponentElementProperties componentElementProperties = new ComponentElementProperties();
componentElementProperties.addComponent(component);
@@ -149,14 +149,14 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
}
private static boolean addToExistingListElement(ExportableComponent component,
- Map<ExportableComponent,ComponentElementProperties> componentToContainingListElement,
- Map<File, Set<ExportableComponent>> fileToComponents) {
+ Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement,
+ MultiMap<File, ExportableComponent> fileToComponents) {
final File[] exportFiles = component.getExportFiles();
File file = null;
for (File exportFile : exportFiles) {
- final Set<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
+ Collection<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
- for (final ExportableComponent tiedComponent : tiedComponents) {
+ for (ExportableComponent tiedComponent : tiedComponents) {
if (tiedComponent == component) continue;
final ComponentElementProperties elementProperties = componentToContainingListElement.get(tiedComponent);
if (elementProperties != null && !FileUtil.filesEqual(exportFile, file)) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
index e82e22d926ea..19a6502b8add 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
@@ -35,7 +35,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
+import org.jetbrains.annotations.NotNull;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -47,10 +49,18 @@ import java.util.jar.JarOutputStream;
public class ExportSettingsAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
Project project = getEventProject(e);
- List<ExportableComponent> exportableComponents = new ArrayList<ExportableComponent>();
- Map<File,Set<ExportableComponent>> fileToComponents = getRegisteredComponentsAndFiles(exportableComponents);
- final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(exportableComponents, fileToComponents, true,
+ ApplicationManager.getApplication().saveSettings();
+
+ MultiMap<File, ExportableComponent> fileToComponents = getExportableComponentsMap();
+ for (Iterator<File> it = fileToComponents.keySet().iterator(); it.hasNext(); ) {
+ File file = it.next();
+ if (!file.exists()) {
+ it.remove();
+ }
+ }
+
+ final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(fileToComponents, true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"));
@@ -65,8 +75,6 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
}
- ApplicationManager.getApplication().saveSettings();
-
final File saveFile = dialog.getExportFile();
try {
if (saveFile.exists()) {
@@ -121,24 +129,18 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
}
}
- public static Map<File, Set<ExportableComponent>> getRegisteredComponentsAndFiles(List<ExportableComponent> exportableComponents) {
- Map<File,Set<ExportableComponent>> fileToComponents = new HashMap<File, Set<ExportableComponent>>();
+ @NotNull
+ public static MultiMap<File, ExportableComponent> getExportableComponentsMap() {
+ MultiMap<File, ExportableComponent> result = MultiMap.createSet();
- final List<ExportableComponent> components = new ArrayList<ExportableComponent>(Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
+ ExportableApplicationComponent[] components1 = ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class);
+ List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
- components.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
-
- for (ExportableComponent component : components) {
- exportableComponents.add(component);
+ for (ExportableComponent component : ContainerUtil.concat(Arrays.asList(components1), components2)) {
for (File exportFile : component.getExportFiles()) {
- Set<ExportableComponent> componentsTied = fileToComponents.get(exportFile);
- if (componentsTied == null) {
- componentsTied = new HashSet<ExportableComponent>();
- fileToComponents.put(exportFile, componentsTied);
- }
- componentsTied.add(component);
+ result.putValue(exportFile, component);
}
}
- return fileToComponents;
+ return result;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
index 1e989946ab2f..f06c45e1af7a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
@@ -36,13 +36,17 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
import java.awt.*;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
@@ -77,10 +81,10 @@ public class ImportSettingsAction extends AnAction implements DumbAware {
return;
}
- final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>();
- final Map<File, Set<ExportableComponent>> filesToComponents = ExportSettingsAction.getRegisteredComponentsAndFiles(registeredComponents);
- List<ExportableComponent> components = getComponentsStored(saveFile, registeredComponents);
- final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(components, filesToComponents, false,
+ MultiMap<File, ExportableComponent> filesToComponents = ExportSettingsAction.getExportableComponentsMap();
+ List<ExportableComponent> components = getComponentsStored(saveFile, ContainerUtil.newArrayList(filesToComponents.values()));
+ filesToComponents.values().retainAll(components);
+ final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(filesToComponents, false,
IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"));
dialog.show();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index 40bfe41fb26f..4a72eda21a3e 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -27,17 +27,20 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
import com.intellij.ui.LicensingFacade;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
public class SendFeedbackAction extends AnAction implements DumbAware {
+ @Override
public void actionPerformed(AnActionEvent e) {
- launchBrowser();
+ launchBrowser(e.getProject());
}
- public static void launchBrowser() {
+ public static void launchBrowser(@Nullable Project project) {
final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
boolean eap = appInfo.isEAP();
String urlTemplate = eap ? appInfo.getEAPFeedbackUrl() : appInfo.getReleaseFeedbackUrl();
@@ -47,7 +50,7 @@ public class SendFeedbackAction extends AnAction implements DumbAware {
.replace("$VERSION", appInfo.getFullVersion())
.replace("$EVAL", isEvaluationLicense() ? "true" : "false")
.replace("$DESCR", getDescription());
- BrowserUtil.browse(urlTemplate);
+ BrowserUtil.browse(urlTemplate, project);
}
private static String getDescription() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
index 851c9096a38b..dde5a5c898dd 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.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.
@@ -27,14 +27,9 @@ public abstract class SplitterActionBase extends AnAction implements DumbAware {
public void update(final AnActionEvent event) {
final Project project = CommonDataKeys.PROJECT.getData(event.getDataContext());
final Presentation presentation = event.getPresentation();
- boolean enabled;
- if (project == null) {
- enabled = false;
- }
- else {
- enabled = isActionEnabled(project);
- }
- if (ActionPlaces.isPopupPlace(event.getPlace())) {
+ boolean inContextMenu = ActionPlaces.isPopupPlace(event.getPlace());
+ boolean enabled = project != null && isActionEnabled(project, inContextMenu);
+ if (inContextMenu) {
presentation.setVisible(enabled);
}
else {
@@ -42,7 +37,17 @@ public abstract class SplitterActionBase extends AnAction implements DumbAware {
}
}
- protected boolean isActionEnabled(Project project) {
+ /**
+ * This method determines whether the action is enabled for {@code project}
+ * if {@code inContextMenu} is set to {@code false}. Otherwise,
+ * it determines whether the action is visible in the context menu.
+ *
+ * @param project the specified project
+ * @param inContextMenu whether the action is used in context menu
+ * @return {@code true} if the action is enabled,
+ * {@code false} otherwise
+ */
+ protected boolean isActionEnabled(Project project, boolean inContextMenu) {
final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
return fileEditorManager.isInSplitter();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 4541f4664751..cb35b5a504f9 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -1071,7 +1071,7 @@ public class Switcher extends AnAction implements DumbAware {
public void layoutContainer(Container target) {
final JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, files);
JComponent filesPane = scrollPane != null ? scrollPane : files;
- if (sBounds == null) {
+ if (sBounds == null || !target.isShowing()) {
super.layoutContainer(target);
sBounds = separator.getBounds();
tBounds = toolWindows.getBounds();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
index 8431364c5d61..7b000f530bdf 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.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.
@@ -18,6 +18,7 @@ package com.intellij.ide.actions;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.tabs.impl.JBEditorTabs;
import javax.swing.*;
@@ -28,7 +29,7 @@ import javax.swing.*;
public class TabsAlphabeticalModeSwitcher extends ToggleAction {
@Override
public boolean isSelected(AnActionEvent e) {
- return JBEditorTabs.isAlphabeticalMode();
+ return Registry.is(JBEditorTabs.TABS_ALPHABETICAL_KEY);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
index 12df75e75656..ec724884ef2d 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.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,8 +32,8 @@ public final class UnsplitAllAction extends SplitterActionBase {
}
@Override
- protected boolean isActionEnabled(Project project) {
+ protected boolean isActionEnabled(Project project, boolean inContextMenu) {
final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
- return fileEditorManager.getWindowSplitCount() > 2;
+ return inContextMenu ? fileEditorManager.getWindowSplitCount() > 2 : fileEditorManager.isInSplitter();
}
}
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 d450cf454291..1af2fb883efb 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
@@ -25,7 +25,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.IconUtil;
-import com.intellij.util.PlatformUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -55,12 +54,12 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/OSXDarcula.png"));
}
else if (SystemInfo.isWindows) {
- if (PlatformUtils.isIdeaCommunity()) {
+ //if (PlatformUtils.isIdeaCommunity()) {
myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/WindowsIntelliJ.png"));
- }
- else {
- myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
- }
+ //}
+ //else {
+ // myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
+ //}
myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/WindowsDarcula.png"));
}
else {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
index e5b9f1530256..b1ea1332986e 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
@@ -25,21 +25,15 @@ import org.jetbrains.annotations.Nullable;
* The interface defines basic password management operations
*/
public interface PasswordStorage {
-
/**
- * @deprecated To remove in IDEA 15. Use {@link #getPassword(Project, Class, String, ModalityState)}
- */
- @Deprecated
- @Nullable
- String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
- /**
- * Get password stored in a password safe.
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * <p>Get password stored in a password safe.</p>
+ *
+ * <p><b>NB: </b>
+ * This method may be called from the background,
+ * and it may need to ask user to enter the master password to access the database by calling
+ * {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()} to show a modal dialog.
+ * So make sure not to call it from the read action.
+ * Calling this method from the dispatch thread is allowed.</p>
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
@@ -49,53 +43,25 @@ public interface PasswordStorage {
* @throws IllegalStateException if the method is called from the read action.
*/
@Nullable
- String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState state) throws PasswordSafeException;
-
+ String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
/**
- * Store password in password safe
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * Remove password stored in a password safe
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
* @param key the key for the password
- * @param value the value to store
+ * @return the plugin key
* @throws PasswordSafeException if password safe cannot be accessed
*/
- void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
-
- /**
- * @deprecated To remove in IDEA 15. Use {@link #storePassword(Project, Class, String, String, ModalityState)}
- */
- @Deprecated
- void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
-
- /**
- * @deprecated To remove in IDEA 15. Use {@link #removePassword(Project, Class, String, ModalityState)}
- */
- @Deprecated
void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
/**
- * Remove password stored in a password safe
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * Store password in password safe
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
* @param key the key for the password
- * @return the plugin key
+ * @param value the value to store
* @throws PasswordSafeException if password safe cannot be accessed
*/
- void removePassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
-
+ void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
index 34aee7aaad38..6d5127b376ad 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
@@ -22,7 +22,6 @@ import com.intellij.ide.passwordSafe.impl.providers.masterKey.MasterKeyPasswordS
import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase;
import com.intellij.ide.passwordSafe.impl.providers.memory.MemoryPasswordSafe;
import com.intellij.ide.passwordSafe.impl.providers.nil.NilProvider;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
@@ -71,19 +70,11 @@ public class PasswordSafeImpl extends PasswordSafe {
}
@Nullable
- @Override
public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
- return getPassword(project, requester, key, null);
- }
-
- @Nullable
- @Override
- public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
- String password = getMemoryProvider().getPassword(project, requester, key, modalityState);
+ String password = getMemoryProvider().getPassword(project, requester, key);
if (password == null) {
- password = provider().getPassword(project, requester, key, modalityState);
+ password = provider().getPassword(project, requester, key);
if (password != null) {
// cache the password in memory as well for easier access during the session
getMemoryProvider().storePassword(project, requester, key, password);
@@ -91,35 +82,21 @@ public class PasswordSafeImpl extends PasswordSafe {
}
return password;
}
- return provider().getPassword(project, requester, key, modalityState);
+ return provider().getPassword(project, requester, key);
}
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- removePassword(project, requestor, key, null);
- }
-
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
getMemoryProvider().removePassword(project, requester, key);
}
- provider().removePassword(project, requester, key, modalityState);
- }
-
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
- storePassword(project, requestor, key, value, null);
+ provider().removePassword(project, requester, key);
}
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
getMemoryProvider().storePassword(project, requester, key, value);
}
- provider().storePassword(project, requester, key, value, modalityState);
+ provider().storePassword(project, requester, key, value);
}
/**
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
index 3a40d617e99b..18dee7c755f5 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
@@ -15,11 +15,7 @@
*/
package com.intellij.ide.passwordSafe.impl;
-import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.PasswordStorage;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* The provider for password safe component
@@ -38,21 +34,4 @@ public abstract class PasswordSafeProvider implements PasswordStorage {
* @return the name of provider
*/
public abstract String getName();
-
- @Nullable
- @Override
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- return getPassword(project, requestor, key, null);
- }
-
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
- storePassword(project, requestor, key, value, null);
- }
-
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- removePassword(project, requestor, key, null);
- }
-
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
index 8c8f921f18b8..a0b001824d90 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
@@ -43,15 +43,13 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
* @throws PasswordSafeException in case of problems with access to the password database.
* @throws IllegalStateException if the method is called from the read action.
*/
- protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
+ protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException;
@Nullable
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requestor, key, modalityState);
+ public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
+ byte[] k = dbKey(project, requestor, key);
byte[] ct = getEncryptedPassword(k);
- return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor, modalityState), ct);
+ return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor), ct);
}
/**
@@ -68,17 +66,14 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
* @param project
* @param requestor the requestor class
* @param key the key to use
- * @param modalityState
* @return the key to use for map
*/
- private byte[] dbKey(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- return EncryptionUtil.dbKey(key(project, requestor, modalityState), requestor, key);
+ private byte[] dbKey(@Nullable Project project, Class requestor, String key) throws PasswordSafeException {
+ return EncryptionUtil.dbKey(key(project, requestor), requestor, key);
}
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requester, key, modalityState);
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
+ byte[] k = dbKey(project, requester, key);
removeEncryptedPassword(k);
}
@@ -89,10 +84,9 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
*/
protected abstract void removeEncryptedPassword(byte[] key);
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requestor, key, modalityState);
- byte[] ct = EncryptionUtil.encryptText(key(project, requestor, modalityState), value);
+ public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
+ byte[] k = dbKey(project, requestor, key);
+ byte[] ct = EncryptionUtil.encryptText(key(project, requestor), value);
storeEncryptedPassword(k, ct);
}
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 b74e51315cd5..840159270a8d 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
@@ -154,8 +154,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- protected byte[] key(@Nullable final Project project, @NotNull final Class requestor,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException {
Application application = ApplicationManager.getApplication();
if (!isTestMode() && application.isHeadlessEnvironment()) {
throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
@@ -200,7 +199,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
}
}
- }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+ }, ModalityState.any());
//noinspection ThrowableResultOfMethodCallIgnored
if (ex.get() != null) {
throw ex.get();
@@ -211,12 +210,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
if (database.isEmpty()) {
return null;
}
- return super.getPassword(project, requestor, key, modalityState);
+ return super.getPassword(project, requestor, key);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
index da82bb986fdb..4989789b4ec0 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
@@ -19,12 +19,10 @@ import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed;
import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider;
import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.security.SecureRandom;
import java.util.Collections;
@@ -60,7 +58,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- protected byte[] key(Project project, @NotNull Class requestor, @Nullable ModalityState modalityState) {
+ protected byte[] key(Project project, @NotNull Class requestor) {
if (key.get() == null) {
byte[] rnd = new byte[EncryptionUtil.SECRET_KEY_SIZE_BYTES * 16];
new SecureRandom().nextBytes(rnd);
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
index e3a77325b06e..4bf024d697c2 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
@@ -17,7 +17,6 @@ package com.intellij.ide.passwordSafe.impl.providers.nil;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,22 +41,16 @@ public final class NilProvider extends PasswordSafeProvider {
return "Do not Store";
}
- @Nullable
- public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
// nothing is stored
return null;
}
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
// do nothing
}
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
// just forget about password
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
index 353e836f3f33..8aa0099ccd1d 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
@@ -73,10 +73,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
/**
* Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -86,13 +83,12 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
public static String askPassword(final Project project,
- @Nullable ModalityState modalityState,
final String title,
final String message,
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword, String error) {
- return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error, null, null);
+ return askPassword(project, title, message, requestor, key, resetPassword, error, null, null);
}
/**
@@ -112,17 +108,14 @@ public class PasswordSafePromptDialog extends DialogWrapper {
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword) {
- return askPassword(null, null, title, message, requestor, key, resetPassword, null);
+ return askPassword(null, title, message, requestor, key, resetPassword, null);
}
/**
* Ask passphrase possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project (might be null)
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -132,13 +125,13 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
public static String askPassphrase(final Project project,
- @Nullable ModalityState modalityState, final String title,
+ final String title,
final String message,
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword,
String error) {
- return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error,
+ return askPassword(project, title, message, requestor, key, resetPassword, error,
"Passphrase:", "Remember the passphrase");
}
@@ -146,10 +139,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
/**
* Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -161,7 +151,6 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
private static String askPassword(final Project project,
- @Nullable ModalityState modalityState,
final String title,
final String message,
@NotNull final Class<?> requestor,
@@ -176,7 +165,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
ps.removePassword(project, requestor, key);
}
else {
- String pw = ps.getPassword(project, requestor, key, modalityState);
+ String pw = ps.getPassword(project, requestor, key);
if (pw != null) {
return pw;
}
@@ -214,7 +203,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
}
}
}
- }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+ }, ModalityState.any());
return ref.get();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
index 20a41e3a886a..931458ff8bc0 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
@@ -161,7 +161,7 @@ public abstract class PluginManagerMain implements Disposable {
g.fillRect(0,0, getWidth(), getHeight());
}
};
- header.setBorder(new CustomLineBorder(UIUtil.getBorderColor(), 1, 1, 0, 1));
+ header.setBorder(new CustomLineBorder(1, 1, 0, 1));
final JLabel mySortLabel = new JLabel();
mySortLabel.setForeground(UIUtil.getLabelDisabledForeground());
mySortLabel.setBorder(new EmptyBorder(1, 1, 1, 5));
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
index be7aa3c8f600..ec763a8d5a76 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
@@ -68,6 +68,8 @@ public class RepositoryHelper {
HttpConfigurable.getInstance().openHttpConnection(url) :
(HttpURLConnection)new URL(url).openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
index 19d924dff777..1036307e97d7 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
@@ -46,6 +46,7 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.content.Content;
import com.intellij.ui.mac.MacPopupMenuUI;
+import com.intellij.ui.popup.OurHeavyWeightPopup;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformUtils;
@@ -853,6 +854,9 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
final Point point = fixPopupLocation(contents, x, y);
final int popupType = UIUtil.isUnderGTKLookAndFeel() ? WEIGHT_HEAVY : PopupUtil.getPopupType(this);
+ if (popupType == WEIGHT_HEAVY && OurHeavyWeightPopup.isEnabled()) {
+ return new OurHeavyWeightPopup(owner, contents, point.x, point.y);
+ }
if (popupType >= 0) {
PopupUtil.setPopupType(myDelegate, popupType);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
index a86a28a375d5..b06cd21daa60 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
@@ -79,7 +79,7 @@ public class DarculaLaf extends BasicLookAndFeel {
@SuppressWarnings("UnusedParameters")
private static void log(Exception e) {
// everything is gonna be alright
- e.printStackTrace();
+// e.printStackTrace();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index 255d356d5bc0..5ddd24560338 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -48,6 +48,13 @@ MenuBar.shadow=3c3f41
MenuBar.darcula.borderColor=555555
MenuBar.darcula.borderShadowColor=282828
+CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI
+CheckBoxMenuItem.borderPainted=false
+
+RadioButtonMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonMenuItemUI
+RadioButtonMenuItem.borderPainted=false
+
+
TabbedPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI
TabbedPane.tabInsets=0,4,0,4
TabbedPane.highlight=292b2d
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java
new file mode 100644
index 000000000000..d9c4ac7895e6
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.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.ide.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.Gray;
+import com.intellij.util.ui.UIUtil;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaCheckBoxMenuItemUI extends DarculaMenuItemUIBase {
+
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaCheckBoxMenuItemUI();
+ }
+
+ protected String getPropertyPrefix() {
+ return "CheckBoxMenuItem";
+ }
+
+ @Override
+ public Dimension getPreferredSize(JComponent c) {
+ return super.getPreferredSize(c);
+ }
+
+ @Override
+ protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+ Graphics2D g = (Graphics2D) g2;
+ final GraphicsConfig config = new GraphicsConfig(g);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+ g.translate(lr.getCheckRect().x-2, lr.getCheckRect().y);
+
+ final int sz = 13;
+ g.setPaint(new GradientPaint(sz / 2, 1, Gray._110, sz / 2, sz, Gray._95));
+ g.fillRoundRect(0, 0, sz, sz - 1 , 4, 4);
+
+ g.setPaint(new GradientPaint(sz / 2, 1, Gray._120.withAlpha(0x5a), sz / 2, sz, Gray._105.withAlpha(90)));
+ g.drawRoundRect(0, (UIUtil.isUnderDarcula() ? 1 : 0), sz, sz - 1, 4, 4);
+
+ g.setPaint(Gray._40.withAlpha(180));
+ g.drawRoundRect(0, 0, sz, sz - 1, 4, 4);
+
+
+ if (lh.getMenuItem().isSelected()) {
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+ g.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+ g.setPaint(Gray._30);
+ g.drawLine(4, 7, 7, 10);
+ g.drawLine(7, 10, sz, 2);
+ g.setPaint(Gray._170);
+ g.drawLine(4, 5, 7, 8);
+ g.drawLine(7, 8, sz, 0);
+ }
+
+ g.translate(-lr.getCheckRect().x+2, -lr.getCheckRect().y);
+ config.restore();
+ g.setColor(foreground);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
new file mode 100644
index 000000000000..cc69d24b6ca3
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
@@ -0,0 +1,208 @@
+/*
+ * 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.ui.laf.darcula.ui;
+
+import sun.swing.MenuItemLayoutHelper;
+import sun.swing.SwingUtilities2;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicMenuItemUI;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaMenuItemUIBase extends BasicMenuItemUI {
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaMenuItemUIBase();
+ }
+
+ public void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement path[], MenuSelectionManager manager) {
+ Point p = e.getPoint();
+ if (p.x >= 0 && p.x < item.getWidth() &&
+ p.y >= 0 && p.y < item.getHeight()) {
+ if (e.getID() == MouseEvent.MOUSE_RELEASED) {
+ manager.clearSelectedPath();
+ item.doClick(0);
+ item.setArmed(false);
+ } else
+ manager.setSelectedPath(path);
+ } else if (item.getModel().isArmed()) {
+ MenuElement newPath[] = new MenuElement[path.length - 1];
+ int i, c;
+ for (i = 0, c = path.length - 1; i < c; i++)
+ newPath[i] = path[i];
+ manager.setSelectedPath(newPath);
+ }
+ }
+
+ protected void paintMenuItem(Graphics g, JComponent c,
+ Icon checkIcon, Icon arrowIcon,
+ Color background, Color foreground,
+ int defaultTextIconGap) {
+ // Save original graphics font and color
+ Font holdf = g.getFont();
+ Color holdc = g.getColor();
+
+ JMenuItem mi = (JMenuItem) c;
+ g.setFont(mi.getFont());
+
+ Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
+ applyInsets(viewRect, mi.getInsets());
+
+ MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
+ arrowIcon, viewRect, defaultTextIconGap, "-", //todo[kb] use protected field BasicMenuItemUI.acceleratorDelimiter when we move to java 1.7
+ mi.getComponentOrientation().isLeftToRight(), mi.getFont(),
+ acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
+ getPropertyPrefix());
+ MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
+
+ paintBackground(g, mi, background);
+ paintCheckIcon(g, lh, lr, holdc, foreground);
+ paintIcon(g, lh, lr, holdc);
+ g.setColor(foreground);
+ paintText(g, lh, lr);
+ paintAccText(g, lh, lr);
+ paintArrowIcon(g, lh, lr, foreground);
+
+ // Restore original graphics font and color
+ g.setColor(holdc);
+ g.setFont(holdf);
+ }
+
+ protected void paintIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
+ if (lh.getIcon() != null) {
+ Icon icon;
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (!model.isEnabled()) {
+ icon = lh.getMenuItem().getDisabledIcon();
+ } else if (model.isPressed() && model.isArmed()) {
+ icon = lh.getMenuItem().getPressedIcon();
+ if (icon == null) {
+ // Use default icon
+ icon = lh.getMenuItem().getIcon();
+ }
+ } else {
+ icon = lh.getMenuItem().getIcon();
+ }
+
+ if (icon != null) {
+ icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
+ lr.getIconRect().y);
+ g.setColor(holdc);
+ }
+ }
+ }
+
+ protected void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr,
+ Color holdc, Color foreground) {
+ if (lh.getCheckIcon() != null) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(foreground);
+ } else {
+ g.setColor(holdc);
+ }
+ if (lh.useCheckAndArrow()) {
+ lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
+ lr.getCheckRect().x, lr.getCheckRect().y);
+ }
+ g.setColor(holdc);
+ }
+ }
+
+ protected void paintAccText(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr) {
+ if (!lh.getAccText().equals("")) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ g.setFont(lh.getAccFontMetrics().getFont());
+ if (!model.isEnabled()) {
+ // *** paint the accText disabled
+ if (disabledForeground != null) {
+ g.setColor(disabledForeground);
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x,
+ lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+ } else {
+ g.setColor(lh.getMenuItem().getBackground().brighter());
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x,
+ lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+ g.setColor(lh.getMenuItem().getBackground().darker());
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x - 1,
+ lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
+ }
+ } else {
+ // *** paint the accText normally
+ if (model.isArmed()
+ || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(acceleratorSelectionForeground);
+ } else {
+ g.setColor(acceleratorForeground);
+ }
+ SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
+ lr.getAccRect().x, lr.getAccRect().y +
+ lh.getAccFontMetrics().getAscent());
+ }
+ }
+ }
+
+ protected void paintText(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr) {
+ if (!lh.getText().equals("")) {
+ if (lh.getHtmlView() != null) {
+ // Text is HTML
+ lh.getHtmlView().paint(g, lr.getTextRect());
+ } else {
+ // Text isn't HTML
+ paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText());
+ }
+ }
+ }
+
+ protected void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr,
+ Color foreground) {
+ if (lh.getArrowIcon() != null) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(foreground);
+ }
+ if (lh.useCheckAndArrow()) {
+ lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
+ lr.getArrowRect().x, lr.getArrowRect().y);
+ }
+ }
+ }
+
+ protected void applyInsets(Rectangle rect, Insets insets) {
+ if(insets != null) {
+ rect.x += insets.left;
+ rect.y += insets.top;
+ rect.width -= (insets.right + rect.x);
+ rect.height -= (insets.bottom + rect.y);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
new file mode 100644
index 000000000000..1048e5d0449b
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.ColorUtil;
+import com.intellij.ui.Gray;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaRadioButtonMenuItemUI extends DarculaMenuItemUIBase {
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaRadioButtonMenuItemUI();
+ }
+
+ protected String getPropertyPrefix() {
+ return "RadioButtonMenuItem";
+ }
+
+ @Override
+ protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+ Graphics2D g = (Graphics2D) g2;
+ final GraphicsConfig config = new GraphicsConfig(g);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+ g.translate(lr.getCheckRect().x-1, lr.getCheckRect().y-1);
+
+ int rad = 5;
+
+ final int x = 0;
+ final int y = 0;
+ final int w = 13;
+ final int h = 13;
+
+ g.translate(x, y);
+
+ //setup AA for lines
+ Color bg = lh.getMenuItem().getBackground();
+ g.setPaint(new GradientPaint(0, 0, ColorUtil.shift(bg, 1.5),
+ 0, 16, ColorUtil.shift(bg, 1.2)));
+
+ g.fillOval(0, 1, w - 1, h - 1);
+
+ g.setPaint(new GradientPaint(w / 2, 1, Gray._160.withAlpha(90), w / 2, h, Gray._100.withAlpha(90)));
+ g.drawOval(0, 2, w - 1, h - 1);
+
+ g.setPaint(Gray._40.withAlpha(200));
+ g.drawOval(0, 1, w - 1, h - 1);
+
+ if (lh.getMenuItem().isSelected()) {
+ final boolean enabled = lh.getMenuItem().isEnabled();
+ g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));
+ g.fillOval((w - rad)/2 , h/2 , rad, rad);
+ g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor"));
+ g.fillOval((w - rad)/2 , h/2 - 1, rad, rad);
+ }
+ config.restore();
+ g.translate(-x, -y);
+
+
+ g.translate(-lr.getCheckRect().x+1, -lr.getCheckRect().y+1);
+ config.restore();
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
index 2b8a8a499621..fcbe27f5c4a5 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
@@ -15,383 +15,89 @@
*/
package com.intellij.ide.util;
-import com.intellij.ui.*;
-import com.intellij.ui.table.JBTable;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.ComponentWithEmptyText;
-import com.intellij.util.ui.StatusText;
-import com.intellij.util.ui.Table;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.*;
+import javax.swing.table.TableCellRenderer;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
/**
* @see ChooseElementsDialog
*/
-public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
- private JBTable myTable = null;
- private MyTableModel myTableModel = null;
- private boolean myColorUnmarkedElements = true;
- private final List<ElementsMarkListener<T>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
- private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+public class ElementsChooser<T> extends MultiStateElementsChooser<T, Boolean> {
+ private static final BooleanMarkStateDescriptor MARK_STATE_DESCRIPTOR = new BooleanMarkStateDescriptor();
public interface ElementsMarkListener<T> {
void elementMarkChanged(T element, boolean isMarked);
}
public ElementsChooser(final boolean elementsCanBeMarked) {
- this(null, false, elementsCanBeMarked);
+ super(elementsCanBeMarked, ElementsChooser.<T>getMarkStateDescriptor());
}
public ElementsChooser(List<T> elements, boolean marked) {
- this(elements, marked, true);
- }
-
- private ElementsChooser(@Nullable List<T> elements, boolean marked, boolean elementsCanBeMarked) {
- super(new BorderLayout());
-
- myTableModel = new MyTableModel(elementsCanBeMarked);
- myTable = new Table(myTableModel);
- myTable.setShowGrid(false);
- myTable.setIntercellSpacing(new Dimension(0, 0));
- myTable.setTableHeader(null);
- myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
- myTable.setColumnSelectionAllowed(false);
- JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
- pane.setPreferredSize(new Dimension(100, 155));
- TableColumnModel columnModel = myTable.getColumnModel();
-
- if (elementsCanBeMarked) {
- TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
- TableUtil.setupCheckboxColumn(checkMarkColumn);
- checkMarkColumn.setCellRenderer(new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
- }
- columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
-
- add(pane, BorderLayout.CENTER);
- myTable.registerKeyboardAction(
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- final int[] selectedRows = myTable.getSelectedRows();
- boolean currentlyMarked = true;
- for (int selectedRow : selectedRows) {
- currentlyMarked = myTableModel.isElementMarked(selectedRow);
- if (!currentlyMarked) {
- break;
- }
- }
- myTableModel.setMarked(selectedRows, !currentlyMarked);
- }
- },
- KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
- JComponent.WHEN_FOCUSED
- );
-
- final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
- @Override
- public int getSelectedIndex() {
- return myTable.getSelectedRow();
- }
-
- @Override
- protected int convertIndexToModel(int viewIndex) {
- return myTable.convertRowIndexToModel(viewIndex);
- }
-
- @Override
- public Object[] getAllElements() {
- final int count = myTableModel.getRowCount();
- Object[] elements = new Object[count];
- for (int idx = 0; idx < count; idx++) {
- elements[idx] = myTableModel.getElementAt(idx);
- }
- return elements;
- }
-
- @Override
- public String getElementText(Object element) {
- return getItemText((T)element);
- }
-
- @Override
- public void selectElement(Object element, String selectedText) {
- final int count = myTableModel.getRowCount();
- for (int row = 0; row < count; row++) {
- if (element.equals(myTableModel.getElementAt(row))) {
- final int viewRow = myTable.convertRowIndexToView(row);
- myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
- TableUtil.scrollSelectionToVisible(myTable);
- break;
- }
- }
- }
- };
- speedSearch.setComparator(new SpeedSearchComparator(false));
- setElements(elements, marked);
- installActions(myTable);
- }
-
- private static void installActions(JTable table) {
- InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
- }
-
- @NotNull
- @Override
- public StatusText getEmptyText() {
- return myTable.getEmptyText();
- }
-
- @NotNull
- @Override
- public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
- return myTable.getExpandableItemsHandler();
- }
-
- @Override
- public void setExpandableItemsEnabled(boolean enabled) {
- myTable.setExpandableItemsEnabled(enabled);
- }
-
- public void setSingleSelectionMode() {
- myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- }
-
- public void refresh() {
- myTableModel.fireTableDataChanged();
- }
-
- public void refresh(T element) {
- final int row = myTableModel.getElementRow(element);
- if (row >= 0) {
- myTableModel.fireTableRowsUpdated(row, row);
- }
- }
-
- private int[] mySavedSelection = null;
- public void saveSelection() {
- mySavedSelection = myTable.getSelectedRows();
- }
-
- public void restoreSelection() {
- if (mySavedSelection != null) {
- TableUtil.selectRows(myTable, mySavedSelection);
- mySavedSelection = null;
- }
- }
-
- public boolean isColorUnmarkedElements() {
- return myColorUnmarkedElements;
- }
-
- public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
- myColorUnmarkedElements = colorUnmarkedElements;
+ super(elements, marked, ElementsChooser.<T>getMarkStateDescriptor());
}
public void addElementsMarkListener(ElementsMarkListener<T> listener) {
- myListeners.add(listener);
+ addElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
}
public void removeElementsMarkListener(ElementsMarkListener<T> listener) {
- myListeners.remove(listener);
- }
-
- public void addListSelectionListener(ListSelectionListener listener) {
- myTable.getSelectionModel().addListSelectionListener(listener);
- }
- public void removeListSelectionListener(ListSelectionListener listener) {
- myTable.getSelectionModel().removeListSelectionListener(listener);
+ removeElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
}
public void addElement(T element, final boolean isMarked) {
- addElement(element, isMarked, element instanceof ElementProperties ? (ElementProperties)element : null);
+ addElement(element, getMarkState(isMarked));
}
/**
* Check if element is marked
+ *
* @param element an element to test
* @return true if element is marked
*/
public boolean isElementMarked(T element) {
- final int elementRow = myTableModel.getElementRow(element);
- return myTableModel.isElementMarked(elementRow);
+ return getElementMarkState(element);
}
/**
- * Check if element is marked
+ * Update element mark
+ *
* @param element an element to test
- * @param marked a new value of mark.
+ * @param marked a new value of mark.
*/
public void setElementMarked(T element, boolean marked) {
- final int elementRow = myTableModel.getElementRow(element);
- myTableModel.setMarked(elementRow, marked);
- }
-
-
- public void removeElement(T element) {
- final int elementRow = myTableModel.getElementRow(element);
- if (elementRow < 0) {
- return; // no such element
- }
- final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
-
- myTableModel.removeElement(element);
- myElementToPropertiesMap.remove(element);
-
- if (wasSelected) {
- final int rowCount = myTableModel.getRowCount();
- if (rowCount > 0) {
- selectRow(elementRow % rowCount);
- }
- else {
- myTable.getSelectionModel().clearSelection();
- }
- }
- myTable.requestFocus();
+ setElementMarkState(element, getMarkState(marked));
}
- public void removeAllElements() {
- myTableModel.removeAllElements();
- myTable.getSelectionModel().clearSelection();
- }
-
- private void selectRow(final int row) {
- myTable.getSelectionModel().setSelectionInterval(row, row);
- myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
- }
-
- public void moveElement(T element, int newRow) {
- final int elementRow = myTableModel.getElementRow(element);
- if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
- return;
- }
- final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
- myTableModel.changeElementRow(element, newRow);
- if (wasSelected) {
- selectRow(newRow);
- }
- }
-
- public interface ElementProperties {
- @Nullable
- Icon getIcon();
- @Nullable
- Color getColor();
- }
public void addElement(T element, final boolean isMarked, ElementProperties elementProperties) {
- myTableModel.addElement(element, isMarked);
- myElementToPropertiesMap.put(element, elementProperties);
- selectRow(myTableModel.getRowCount() - 1);
- myTable.requestFocus();
- }
-
- public void setElementProperties(T element, ElementProperties properties) {
- myElementToPropertiesMap.put(element, properties);
+ addElement(element, getMarkState(isMarked), elementProperties);
}
public void setElements(List<T> elements, boolean marked) {
- myTableModel.clear();
- myTableModel.addElements(elements, marked);
- }
-
- @Nullable
- public T getSelectedElement() {
- final int selectedRow = getSelectedElementRow();
- return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
- }
-
- public int getSelectedElementRow() {
- return myTable.getSelectedRow();
- }
-
- @NotNull
- public List<T> getSelectedElements() {
- final List<T> elements = new ArrayList<T>();
- final int[] selectedRows = myTable.getSelectedRows();
- for (int selectedRow : selectedRows) {
- if (selectedRow < 0) {
- continue;
- }
- elements.add(myTableModel.getElementAt(selectedRow));
- }
- return elements;
- }
-
- public void selectElements(Collection<? extends T> elements) {
- if (elements.isEmpty()) {
- myTable.clearSelection();
- return;
- }
- final int[] rows = getElementsRows(elements);
- TableUtil.selectRows(myTable, rows);
- TableUtil.scrollSelectionToVisible(myTable);
- myTable.requestFocus();
- }
-
- private int[] getElementsRows(final Collection<? extends T> elements) {
- final int[] rows = new int[elements.size()];
- int index = 0;
- for (final T element : elements) {
- rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
- }
- return rows;
+ setElements(elements, getMarkState(marked));
}
public void markElements(Collection<T> elements) {
- myTableModel.setMarked(getElementsRows(elements), true);
+ markElements(elements, Boolean.TRUE);
}
@NotNull
public List<T> getMarkedElements() {
- final int count = myTableModel.getRowCount();
+ Map<T, Boolean> elementMarkStates = getElementMarkStates();
List<T> elements = new ArrayList<T>();
- for (int idx = 0; idx < count; idx++) {
- final T element = myTableModel.getElementAt(idx);
- if (myTableModel.isElementMarked(idx)) {
- elements.add(element);
+ for (Map.Entry<T, Boolean> entry : elementMarkStates.entrySet()) {
+ if (entry.getValue()) {
+ elements.add(entry.getKey());
}
}
return elements;
}
- public void sort(Comparator<T> comparator) {
- myTableModel.sort(comparator);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- myTable.setRowSelectionAllowed(enabled);
- myTableModel.fireTableDataChanged();
- }
-
- public void stopEditing() {
- TableCellEditor editor = myTable.getCellEditor();
- if (editor != null) {
- editor.stopCellEditing();
- }
- }
-
- public JComponent getComponent() {
- return myTable;
- }
-
public void invertSelection() {
final int count = getElementCount();
for (int i = 0; i < count; i++) {
@@ -401,264 +107,89 @@ public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText
}
public void setAllElementsMarked(boolean marked) {
- final int[] rows = new int[myTableModel.getRowCount()];
- for (int idx = 0; idx < rows.length; idx++) {
- rows[idx] = idx;
- }
- myTableModel.setMarked(rows, marked);
- }
-
- private void notifyElementMarked(T element, boolean isMarked) {
- for (ElementsMarkListener<T> listener : myListeners) {
- listener.elementMarkChanged(element, isMarked);
- }
+ setAllElementsMarked(getMarkState(marked));
}
- public void clear() {
- myTableModel.clear();
- myElementToPropertiesMap.clear();
+ private static Boolean getMarkState(boolean marked) {
+ return marked;
}
- public int getElementCount() {
- return myTableModel.getRowCount();
+ @SuppressWarnings("unchecked")
+ private static <T> MarkStateDescriptor<T, Boolean> getMarkStateDescriptor() {
+ return MARK_STATE_DESCRIPTOR;
}
- public T getElementAt(int row) {
- return myTableModel.getElementAt(row);
- }
-
- public void disableElement(T element) {
- myDisabledMap.put(element, Boolean.TRUE);
- }
-
- private final class MyTableModel extends AbstractTableModel {
- private final List<T> myElements = new ArrayList<T>();
- private final Map<T, Boolean> myMarkedMap = new HashMap<T, Boolean>();
- public final int CHECK_MARK_COLUM_INDEX;
- public final int ELEMENT_COLUMN_INDEX;
- private final boolean myElementsCanBeMarked;
-
- public MyTableModel(final boolean elementsCanBeMarked) {
- myElementsCanBeMarked = elementsCanBeMarked;
- if (elementsCanBeMarked) {
- CHECK_MARK_COLUM_INDEX = 0;
- ELEMENT_COLUMN_INDEX = 1;
- }
- else {
- CHECK_MARK_COLUM_INDEX = -1;
- ELEMENT_COLUMN_INDEX = 0;
- }
- }
-
- public void sort(Comparator<T> comparator) {
- Collections.sort(myElements, comparator);
- fireTableDataChanged();
- }
-
- public T getElementAt(int index) {
- return myElements.get(index);
- }
-
- public boolean isElementMarked(int index) {
- final T element = myElements.get(index);
- final Boolean isMarked = myMarkedMap.get(element);
- return isMarked.booleanValue();
- }
-
- private void addElement(T element, boolean isMarked) {
- myElements.add(element);
- myMarkedMap.put(element, isMarked? Boolean.TRUE : Boolean.FALSE);
- int row = myElements.size() - 1;
- fireTableRowsInserted(row, row);
- }
-
- private void addElements(@Nullable List<T> elements, boolean isMarked) {
- if (elements == null || elements.isEmpty()) {
- return;
- }
- for (final T element : elements) {
- myElements.add(element);
- myMarkedMap.put(element, isMarked ? Boolean.TRUE : Boolean.FALSE);
- }
- fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
- }
-
- public void removeElement(T element) {
- final boolean reallyRemoved = myElements.remove(element);
- if (reallyRemoved) {
- myMarkedMap.remove(element);
- fireTableDataChanged();
- }
- }
-
- public void changeElementRow(T element, int row) {
- final boolean reallyRemoved = myElements.remove(element);
- if (reallyRemoved) {
- myElements.add(row, element);
- fireTableDataChanged();
- }
- }
-
- public int getElementRow(T element) {
- return myElements.indexOf(element);
- }
-
- public void removeAllElements() {
- myElements.clear();
- fireTableDataChanged();
- }
-
- public void removeRows(int[] rows) {
- final List<T> toRemove = new ArrayList<T>();
- for (int row : rows) {
- final T element = myElements.get(row);
- toRemove.add(element);
- myMarkedMap.remove(element);
- }
- myElements.removeAll(toRemove);
- fireTableDataChanged();
- }
-
+ private static class BooleanMarkStateDescriptor<T> implements MarkStateDescriptor<T, Boolean> {
+ @NotNull
@Override
- public int getRowCount() {
- return myElements.size();
+ public Boolean getDefaultState(@NotNull T element) {
+ return Boolean.FALSE;
}
+ @NotNull
@Override
- public int getColumnCount() {
- return myElementsCanBeMarked? 2 : 1;
+ public Boolean getNextState(@NotNull T element, @NotNull Boolean state) {
+ return !state;
}
- @Override
@Nullable
- public Object getValueAt(int rowIndex, int columnIndex) {
- T element = myElements.get(rowIndex);
- if (columnIndex == ELEMENT_COLUMN_INDEX) {
- return element;
- }
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- return myMarkedMap.get(element);
- }
- return null;
- }
-
@Override
- public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- setMarked(rowIndex, ((Boolean)aValue).booleanValue());
- }
- }
-
- private void setMarked(int rowIndex, final boolean marked) {
- final T element = myElements.get(rowIndex);
- final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
- final Boolean prevValue = myMarkedMap.put(element, newValue);
- fireTableRowsUpdated(rowIndex, rowIndex);
- if (!newValue.equals(prevValue)) {
- notifyElementMarked(element, marked);
- }
- }
-
- private void setMarked(int[] rows, final boolean marked) {
- if (rows == null || rows.length == 0) {
- return;
- }
- int firstRow = Integer.MAX_VALUE;
- int lastRow = Integer.MIN_VALUE;
- final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
- for (final int row : rows) {
- final T element = myElements.get(row);
- final Boolean prevValue = myMarkedMap.put(element, newValue);
- if (!newValue.equals(prevValue)) {
- notifyElementMarked(element, newValue.booleanValue());
+ public Boolean getNextState(@NotNull Map<T, Boolean> elementsWithStates) {
+ boolean currentlyMarked = true;
+ for (Boolean state : elementsWithStates.values()) {
+ currentlyMarked = state;
+ if (!currentlyMarked) {
+ break;
}
- firstRow = Math.min(firstRow, row);
- lastRow = Math.max(lastRow, row);
}
- fireTableRowsUpdated(firstRow, lastRow);
+ return !currentlyMarked;
}
@Override
- public Class getColumnClass(int columnIndex) {
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- return Boolean.class;
- }
- return super.getColumnClass(columnIndex);
+ public boolean isMarked(@NotNull Boolean state) {
+ return state;
}
+ @Nullable
@Override
- public boolean isCellEditable(int rowIndex, int columnIndex) {
- if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
- return false;
- }
- final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
- return myDisabledMap.get(o) == null;
+ public Boolean getMarkState(@Nullable Object value) {
+ return value instanceof Boolean ? ((Boolean)value) : null;
}
- public void clear() {
- myElements.clear();
- myMarkedMap.clear();
- fireTableDataChanged();
+ @Nullable
+ @Override
+ public TableCellRenderer getMarkRenderer() {
+ return null;
}
}
- protected String getItemText(@NotNull T value) {
- return value.toString();
- }
+ private static class ElementsMarkStateListenerAdapter<T> implements ElementsMarkStateListener<T, Boolean> {
+ private final ElementsMarkListener<T> myListener;
- @Nullable
- protected Icon getItemIcon(@NotNull T value) {
- return null;
- }
+ public ElementsMarkStateListenerAdapter(ElementsMarkListener<T> listener) {
+ myListener = listener;
+ }
- private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
@Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- final Color color = UIUtil.getTableFocusCellBackground();
- Component component;
- T t = (T)value;
- try {
- UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
- component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- setText(t != null ? getItemText(t) : "");
- if (component instanceof JLabel) {
- ((JLabel)component).setBorder(noFocusBorder);
- }
- }
- finally {
- UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
- }
- final MyTableModel model = (MyTableModel)table.getModel();
- component.setEnabled(ElementsChooser.this.isEnabled() && (!myColorUnmarkedElements || model.isElementMarked(row)));
- final ElementProperties properties = myElementToPropertiesMap.get(t);
- if (component instanceof JLabel) {
- final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
- JLabel label = (JLabel)component;
- label.setIcon(icon);
- label.setDisabledIcon(icon);
- }
- component.setForeground(properties != null && properties.getColor() != null ?
- properties.getColor() :
- isSelected ? table.getSelectionForeground() : table.getForeground());
- return component;
+ public void elementMarkChanged(T element, Boolean markState) {
+ myListener.elementMarkChanged(element, markState);
}
- }
- private class CheckMarkColumnCellRenderer implements TableCellRenderer {
- private final TableCellRenderer myDelegate;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ElementsMarkStateListenerAdapter that = (ElementsMarkStateListenerAdapter)o;
- public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
- myDelegate = delegate;
+ if (!myListener.equals(that.myListener)) return false;
+
+ return true;
}
@Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- component.setEnabled(isEnabled());
- if (component instanceof JComponent) {
- ((JComponent)component).setBorder(null);
- }
- return component;
+ public int hashCode() {
+ return myListener.hashCode();
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
new file mode 100644
index 000000000000..bccbd7b144ac
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
@@ -0,0 +1,692 @@
+/*
+ * 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.util;
+
+import com.intellij.ui.*;
+import com.intellij.ui.table.JBTable;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ComponentWithEmptyText;
+import com.intellij.util.ui.StatusText;
+import com.intellij.util.ui.Table;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.*;
+import java.util.List;
+
+public class MultiStateElementsChooser<T, S> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
+ private MarkStateDescriptor<T, S> myMarkStateDescriptor;
+ private JBTable myTable = null;
+ private MyTableModel myTableModel = null;
+ private boolean myColorUnmarkedElements = true;
+ private final List<ElementsMarkStateListener<T, S>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
+ private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+
+ public interface ElementsMarkStateListener<T, S> {
+ void elementMarkChanged(T element, S markState);
+ }
+
+ public interface MarkStateDescriptor<T, S> {
+ @NotNull
+ S getDefaultState(@NotNull T element);
+
+ @NotNull
+ S getNextState(@NotNull T element, @NotNull S state);
+
+ @Nullable
+ S getNextState(@NotNull Map<T, S> elementsWithStates);
+
+ boolean isMarked(@NotNull S state);
+
+ @Nullable
+ S getMarkState(@Nullable Object value);
+
+ @Nullable
+ TableCellRenderer getMarkRenderer();
+ }
+
+ public MultiStateElementsChooser(final boolean elementsCanBeMarked, MarkStateDescriptor<T, S> markStateDescriptor) {
+ this(null, null, elementsCanBeMarked, markStateDescriptor);
+ }
+
+ public MultiStateElementsChooser(List<T> elements, S markState, MarkStateDescriptor<T, S> markStateDescriptor) {
+ this(elements, markState, true, markStateDescriptor);
+ }
+
+ private MultiStateElementsChooser(@Nullable List<T> elements,
+ S markState,
+ boolean elementsCanBeMarked,
+ MarkStateDescriptor<T, S> markStateDescriptor) {
+ super(new BorderLayout());
+
+ myMarkStateDescriptor = markStateDescriptor;
+
+ myTableModel = new MyTableModel(elementsCanBeMarked);
+ myTable = new Table(myTableModel);
+ myTable.setShowGrid(false);
+ myTable.setIntercellSpacing(new Dimension(0, 0));
+ myTable.setTableHeader(null);
+ myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ myTable.setColumnSelectionAllowed(false);
+ JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
+ pane.setPreferredSize(new Dimension(100, 155));
+ TableColumnModel columnModel = myTable.getColumnModel();
+
+ if (elementsCanBeMarked) {
+ TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
+ TableUtil.setupCheckboxColumn(checkMarkColumn);
+ TableCellRenderer checkMarkRenderer = myMarkStateDescriptor.getMarkRenderer();
+ if (checkMarkRenderer == null) {
+ checkMarkRenderer = new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class));
+ }
+ checkMarkColumn.setCellRenderer(checkMarkRenderer);
+ }
+ columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
+
+ add(pane, BorderLayout.CENTER);
+ myTable.registerKeyboardAction(
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ final int[] selectedRows = myTable.getSelectedRows();
+ Map<T, S> selectedElements = new LinkedHashMap<T, S>(selectedRows.length);
+ for (int selectedRow : selectedRows) {
+ selectedElements.put(myTableModel.getElementAt(selectedRow), myTableModel.getElementMarkState(selectedRow));
+ }
+ S nextState = myMarkStateDescriptor.getNextState(selectedElements);
+ if (nextState != null) {
+ myTableModel.setMarkState(selectedRows, nextState);
+ }
+ }
+ },
+ KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
+ JComponent.WHEN_FOCUSED
+ );
+
+ final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
+ @Override
+ public int getSelectedIndex() {
+ return myTable.getSelectedRow();
+ }
+
+ @Override
+ protected int convertIndexToModel(int viewIndex) {
+ return myTable.convertRowIndexToModel(viewIndex);
+ }
+
+ @Override
+ public Object[] getAllElements() {
+ final int count = myTableModel.getRowCount();
+ Object[] elements = new Object[count];
+ for (int idx = 0; idx < count; idx++) {
+ elements[idx] = myTableModel.getElementAt(idx);
+ }
+ return elements;
+ }
+
+ @Override
+ public String getElementText(Object element) {
+ return getItemText((T)element);
+ }
+
+ @Override
+ public void selectElement(Object element, String selectedText) {
+ final int count = myTableModel.getRowCount();
+ for (int row = 0; row < count; row++) {
+ if (element.equals(myTableModel.getElementAt(row))) {
+ final int viewRow = myTable.convertRowIndexToView(row);
+ myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
+ TableUtil.scrollSelectionToVisible(myTable);
+ break;
+ }
+ }
+ }
+ };
+ speedSearch.setComparator(new SpeedSearchComparator(false));
+ setElements(elements, markState);
+ installActions(myTable);
+ }
+
+ private static void installActions(JTable table) {
+ InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
+ }
+
+ @NotNull
+ @Override
+ public StatusText getEmptyText() {
+ return myTable.getEmptyText();
+ }
+
+ @NotNull
+ @Override
+ public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
+ return myTable.getExpandableItemsHandler();
+ }
+
+ @Override
+ public void setExpandableItemsEnabled(boolean enabled) {
+ myTable.setExpandableItemsEnabled(enabled);
+ }
+
+ public void setSingleSelectionMode() {
+ myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ }
+
+ public void refresh() {
+ myTableModel.fireTableDataChanged();
+ }
+
+ public void refresh(T element) {
+ final int row = myTableModel.getElementRow(element);
+ if (row >= 0) {
+ myTableModel.fireTableRowsUpdated(row, row);
+ }
+ }
+
+ private int[] mySavedSelection = null;
+ public void saveSelection() {
+ mySavedSelection = myTable.getSelectedRows();
+ }
+
+ public void restoreSelection() {
+ if (mySavedSelection != null) {
+ TableUtil.selectRows(myTable, mySavedSelection);
+ mySavedSelection = null;
+ }
+ }
+
+ public boolean isColorUnmarkedElements() {
+ return myColorUnmarkedElements;
+ }
+
+ public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
+ myColorUnmarkedElements = colorUnmarkedElements;
+ }
+
+ public void addElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+ myListeners.add(listener);
+ }
+
+ public void removeElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+ myListeners.remove(listener);
+ }
+
+ public void addListSelectionListener(ListSelectionListener listener) {
+ myTable.getSelectionModel().addListSelectionListener(listener);
+ }
+ public void removeListSelectionListener(ListSelectionListener listener) {
+ myTable.getSelectionModel().removeListSelectionListener(listener);
+ }
+
+ public void addElement(T element, final S markState) {
+ addElement(element, markState, element instanceof ElementProperties ? (ElementProperties)element : null);
+ }
+
+ /**
+ * Gets element mark state
+ * @param element an element to test
+ * @return state of element
+ */
+ public S getElementMarkState(T element) {
+ final int elementRow = myTableModel.getElementRow(element);
+ return myTableModel.getElementMarkState(elementRow);
+ }
+
+ /**
+ * Update element mark state
+ * @param element an element to test
+ * @param markState a new value of mark state
+ */
+ public void setElementMarkState(T element, S markState) {
+ final int elementRow = myTableModel.getElementRow(element);
+ myTableModel.setMarkState(elementRow, markState);
+ }
+
+
+ public void removeElement(T element) {
+ final int elementRow = myTableModel.getElementRow(element);
+ if (elementRow < 0) {
+ return; // no such element
+ }
+ final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+
+ myTableModel.removeElement(element);
+ myElementToPropertiesMap.remove(element);
+
+ if (wasSelected) {
+ final int rowCount = myTableModel.getRowCount();
+ if (rowCount > 0) {
+ selectRow(elementRow % rowCount);
+ }
+ else {
+ myTable.getSelectionModel().clearSelection();
+ }
+ }
+ myTable.requestFocus();
+ }
+
+ public void removeAllElements() {
+ myTableModel.removeAllElements();
+ myTable.getSelectionModel().clearSelection();
+ }
+
+ private void selectRow(final int row) {
+ myTable.getSelectionModel().setSelectionInterval(row, row);
+ myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
+ }
+
+ public void moveElement(T element, int newRow) {
+ final int elementRow = myTableModel.getElementRow(element);
+ if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
+ return;
+ }
+ final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+ myTableModel.changeElementRow(element, newRow);
+ if (wasSelected) {
+ selectRow(newRow);
+ }
+ }
+
+ public interface ElementProperties {
+ @Nullable
+ Icon getIcon();
+ @Nullable
+ Color getColor();
+ }
+
+ public void addElement(T element, final S markState, ElementProperties elementProperties) {
+ myTableModel.addElement(element, markState);
+ myElementToPropertiesMap.put(element, elementProperties);
+ selectRow(myTableModel.getRowCount() - 1);
+ myTable.requestFocus();
+ }
+
+ public void setElementProperties(T element, ElementProperties properties) {
+ myElementToPropertiesMap.put(element, properties);
+ }
+
+ public void setElements(List<T> elements, S markState) {
+ myTableModel.clear();
+ myTableModel.addElements(elements, markState);
+ }
+
+ @Nullable
+ public T getSelectedElement() {
+ final int selectedRow = getSelectedElementRow();
+ return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
+ }
+
+ public int getSelectedElementRow() {
+ return myTable.getSelectedRow();
+ }
+
+ @NotNull
+ public List<T> getSelectedElements() {
+ final List<T> elements = new ArrayList<T>();
+ final int[] selectedRows = myTable.getSelectedRows();
+ for (int selectedRow : selectedRows) {
+ if (selectedRow < 0) {
+ continue;
+ }
+ elements.add(myTableModel.getElementAt(selectedRow));
+ }
+ return elements;
+ }
+
+ public void selectElements(Collection<? extends T> elements) {
+ if (elements.isEmpty()) {
+ myTable.clearSelection();
+ return;
+ }
+ final int[] rows = getElementsRows(elements);
+ TableUtil.selectRows(myTable, rows);
+ TableUtil.scrollSelectionToVisible(myTable);
+ myTable.requestFocus();
+ }
+
+ private int[] getElementsRows(final Collection<? extends T> elements) {
+ final int[] rows = new int[elements.size()];
+ int index = 0;
+ for (final T element : elements) {
+ rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
+ }
+ return rows;
+ }
+
+ public void markElements(Collection<T> elements, S markState) {
+ myTableModel.setMarkState(getElementsRows(elements), markState);
+ }
+
+ @NotNull
+ public Map<T, S> getElementMarkStates() {
+ final int count = myTableModel.getRowCount();
+ Map<T, S> elements = new LinkedHashMap<T, S>();
+ for (int idx = 0; idx < count; idx++) {
+ final T element = myTableModel.getElementAt(idx);
+ elements.put(element, myTableModel.getElementMarkState(idx));
+ }
+ return elements;
+ }
+
+ public void sort(Comparator<T> comparator) {
+ myTableModel.sort(comparator);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ myTable.setRowSelectionAllowed(enabled);
+ myTableModel.fireTableDataChanged();
+ }
+
+ public void stopEditing() {
+ TableCellEditor editor = myTable.getCellEditor();
+ if (editor != null) {
+ editor.stopCellEditing();
+ }
+ }
+
+ public JComponent getComponent() {
+ return myTable;
+ }
+
+ public void setAllElementsMarked(S markState) {
+ final int[] rows = new int[myTableModel.getRowCount()];
+ for (int idx = 0; idx < rows.length; idx++) {
+ rows[idx] = idx;
+ }
+ myTableModel.setMarkState(rows, markState);
+ }
+
+ private void notifyElementMarked(T element, S markState) {
+ for (ElementsMarkStateListener<T, S> listener : myListeners) {
+ listener.elementMarkChanged(element, markState);
+ }
+ }
+
+ public void clear() {
+ myTableModel.clear();
+ myElementToPropertiesMap.clear();
+ }
+
+ public int getElementCount() {
+ return myTableModel.getRowCount();
+ }
+
+ public T getElementAt(int row) {
+ return myTableModel.getElementAt(row);
+ }
+
+ public void disableElement(T element) {
+ myDisabledMap.put(element, Boolean.TRUE);
+ }
+
+ private final class MyTableModel extends AbstractTableModel {
+ private final List<T> myElements = new ArrayList<T>();
+ private final Map<T, S> myMarkedMap = new HashMap<T, S>();
+ public final int CHECK_MARK_COLUM_INDEX;
+ public final int ELEMENT_COLUMN_INDEX;
+ private final boolean myElementsCanBeMarked;
+
+ public MyTableModel(final boolean elementsCanBeMarked) {
+ myElementsCanBeMarked = elementsCanBeMarked;
+ if (elementsCanBeMarked) {
+ CHECK_MARK_COLUM_INDEX = 0;
+ ELEMENT_COLUMN_INDEX = 1;
+ }
+ else {
+ CHECK_MARK_COLUM_INDEX = -1;
+ ELEMENT_COLUMN_INDEX = 0;
+ }
+ }
+
+ public void sort(Comparator<T> comparator) {
+ Collections.sort(myElements, comparator);
+ fireTableDataChanged();
+ }
+
+ public T getElementAt(int index) {
+ return myElements.get(index);
+ }
+
+ public S getElementMarkState(int index) {
+ final T element = myElements.get(index);
+ return myMarkedMap.get(element);
+ }
+
+ private void addElement(T element, S markState) {
+ myElements.add(element);
+ myMarkedMap.put(element, notNullMarkState(element, markState));
+ int row = myElements.size() - 1;
+ fireTableRowsInserted(row, row);
+ }
+
+ private void addElements(@Nullable List<T> elements, S markState) {
+ if (elements == null || elements.isEmpty()) {
+ return;
+ }
+ for (final T element : elements) {
+ myElements.add(element);
+ myMarkedMap.put(element, notNullMarkState(element, markState));
+ }
+ fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
+ }
+
+ public void removeElement(T element) {
+ final boolean reallyRemoved = myElements.remove(element);
+ if (reallyRemoved) {
+ myMarkedMap.remove(element);
+ fireTableDataChanged();
+ }
+ }
+
+ public void changeElementRow(T element, int row) {
+ final boolean reallyRemoved = myElements.remove(element);
+ if (reallyRemoved) {
+ myElements.add(row, element);
+ fireTableDataChanged();
+ }
+ }
+
+ public int getElementRow(T element) {
+ return myElements.indexOf(element);
+ }
+
+ public void removeAllElements() {
+ myElements.clear();
+ fireTableDataChanged();
+ }
+
+ public void removeRows(int[] rows) {
+ final List<T> toRemove = new ArrayList<T>();
+ for (int row : rows) {
+ final T element = myElements.get(row);
+ toRemove.add(element);
+ myMarkedMap.remove(element);
+ }
+ myElements.removeAll(toRemove);
+ fireTableDataChanged();
+ }
+
+ @Override
+ public int getRowCount() {
+ return myElements.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return myElementsCanBeMarked? 2 : 1;
+ }
+
+ @Override
+ @Nullable
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ T element = myElements.get(rowIndex);
+ if (columnIndex == ELEMENT_COLUMN_INDEX) {
+ return element;
+ }
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ return myMarkedMap.get(element);
+ }
+ return null;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ S nextState = myMarkStateDescriptor.getMarkState(aValue);
+ if (nextState == null) {
+ T element = myTableModel.getElementAt(rowIndex);
+ S currentState = myTableModel.getElementMarkState(rowIndex);
+ nextState = myMarkStateDescriptor.getNextState(element, currentState);
+ }
+ setMarkState(rowIndex, nextState);
+ }
+ }
+
+ private void setMarkState(int rowIndex, final S markState) {
+ final T element = myElements.get(rowIndex);
+ final S newValue = notNullMarkState(element, markState);
+ final S prevValue = myMarkedMap.put(element, newValue);
+ fireTableRowsUpdated(rowIndex, rowIndex);
+ if (!newValue.equals(prevValue)) {
+ notifyElementMarked(element, newValue);
+ }
+ }
+
+ private void setMarkState(int[] rows, final S markState) {
+ if (rows == null || rows.length == 0) {
+ return;
+ }
+ int firstRow = Integer.MAX_VALUE;
+ int lastRow = Integer.MIN_VALUE;
+ for (final int row : rows) {
+ final T element = myElements.get(row);
+ final S newValue = notNullMarkState(element, markState);
+ final S prevValue = myMarkedMap.put(element, newValue);
+ if (!newValue.equals(prevValue)) {
+ notifyElementMarked(element, newValue);
+ }
+ firstRow = Math.min(firstRow, row);
+ lastRow = Math.max(lastRow, row);
+ }
+ fireTableRowsUpdated(firstRow, lastRow);
+ }
+
+ @NotNull
+ private S notNullMarkState(T element, S markState) {
+ return markState != null ? markState : myMarkStateDescriptor.getDefaultState(element);
+ }
+
+ @Override
+ public Class getColumnClass(int columnIndex) {
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ return Boolean.class;
+ }
+ return super.getColumnClass(columnIndex);
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
+ return false;
+ }
+ final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
+ return myDisabledMap.get(o) == null;
+ }
+
+ public void clear() {
+ myElements.clear();
+ myMarkedMap.clear();
+ fireTableDataChanged();
+ }
+ }
+
+ protected String getItemText(@NotNull T value) {
+ return value.toString();
+ }
+
+ @Nullable
+ protected Icon getItemIcon(@NotNull T value) {
+ return null;
+ }
+
+ private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ final Color color = UIUtil.getTableFocusCellBackground();
+ Component component;
+ T t = (T)value;
+ try {
+ UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
+ component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ setText(t != null ? getItemText(t) : "");
+ if (component instanceof JLabel) {
+ ((JLabel)component).setBorder(noFocusBorder);
+ }
+ }
+ finally {
+ UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
+ }
+ final MyTableModel model = (MyTableModel)table.getModel();
+ component.setEnabled(MultiStateElementsChooser.this.isEnabled() &&
+ (!myColorUnmarkedElements || myMarkStateDescriptor.isMarked(model.getElementMarkState(row))));
+ final ElementProperties properties = myElementToPropertiesMap.get(t);
+ if (component instanceof JLabel) {
+ final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
+ JLabel label = (JLabel)component;
+ label.setIcon(icon);
+ label.setDisabledIcon(icon);
+ }
+ component.setForeground(properties != null && properties.getColor() != null ?
+ properties.getColor() :
+ isSelected ? table.getSelectionForeground() : table.getForeground());
+ return component;
+ }
+ }
+
+ private class CheckMarkColumnCellRenderer implements TableCellRenderer {
+ private final TableCellRenderer myDelegate;
+
+ public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
+ myDelegate = delegate;
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ component.setEnabled(isEnabled());
+ if (component instanceof JComponent) {
+ ((JComponent)component).setBorder(null);
+ }
+ return component;
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
index 897491532833..2873ed3a222a 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.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.
@@ -21,12 +21,11 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Function;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
@@ -60,19 +59,11 @@ public class IdeSettingsStatisticsUtils {
@Nullable
private static Object getPropertyValue(Object componentInstance, String propertyName) {
final Class<? extends Object> componentInstanceClass = componentInstance.getClass();
- Object propertyValue = null;
- try {
- Field field = componentInstanceClass.getDeclaredField(propertyName);
- propertyValue = field.get(componentInstance);
- }
- catch (NoSuchFieldException ignored) {
- }
- catch (IllegalAccessException ignored) {
- }
+ Object propertyValue = ReflectionUtil.getField(componentInstanceClass, componentInstance, null, propertyName);
if (propertyValue == null) {
- Method method = getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
+ Method method = ReflectionUtil.getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
if (method == null) {
- method = getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
+ method = ReflectionUtil.getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
}
if (method != null) {
try {
@@ -85,16 +76,6 @@ public class IdeSettingsStatisticsUtils {
return propertyValue;
}
- @Nullable
- private static Method getMethod(@NotNull Class componentInstanceClass, @NotNull String name) {
- try {
- return componentInstanceClass.getMethod(name);
- }
- catch (NoSuchMethodException ignored) {
- }
- return null;
- }
-
private static String getUsageDescriptorKey(@NotNull String providerName, @NotNull String name, @NotNull String value) {
final String shortName = StringUtil.getShortName(providerName);
return shortName + "#" + name + "(" + value + ")";
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
index 73af2c304beb..2d6a768a92c2 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.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.
@@ -22,6 +22,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.ComboBoxTableRenderer;
import com.intellij.openapi.ui.StripeTable;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.TableSpeedSearch;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ui.UIUtil;
@@ -30,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -126,6 +128,22 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable
final TableColumn idColumn = getColumnModel().getColumn(ID_COLUMN);
idColumn.setPreferredWidth(200);
+ idColumn.setCellRenderer(new DefaultTableCellRenderer() {
+ @NotNull
+ @Override
+ public Component getTableCellRendererComponent(@NotNull JTable table,
+ Object value,
+ boolean isSelected,
+ boolean hasFocus,
+ int row,
+ int column) {
+ Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ if (component instanceof JComponent) {
+ ((JComponent)component).setBorder(IdeBorderFactory.createEmptyBorder(0, 4, 0, 4));
+ }
+ return component;
+ }
+ });
final TableColumn displayTypeColumn = getColumnModel().getColumn(DISPLAY_TYPE_COLUMN);
displayTypeColumn.setMaxWidth(300);
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index ed40589a7d20..8120b0644675 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.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.
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils;
-import com.intellij.util.SystemProperties;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -423,15 +422,12 @@ public class ConfigImportHelper {
dir = dir.substring(1, dir.length() - 1);
}
if (replaceUserHome) {
- if (dir.startsWith("~\\") || dir.startsWith("~//") || StringUtil.startsWithConcatenation(dir, "~", File.separator)) {
- dir = SystemProperties.getUserHome() + dir.substring(1);
- }
+ dir = FileUtil.expandUserHome(dir);
}
return dir;
}
- public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome,
- @NotNull final ConfigImportSettings settings) {
+ public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, @NotNull final ConfigImportSettings settings) {
if (new File(installationHome, OPTIONS_XML).exists()) return true;
if (new File(installationHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) return true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
index b0d4d3f909c2..005c006d1717 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.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,8 +15,7 @@
*/
package com.intellij.openapi.application;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.util.SystemProperties;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,10 +73,7 @@ public class ConfigImportSettings {
}
protected String getAutoImportLabel(File guessedOldConfig) {
- String path = guessedOldConfig.getAbsolutePath();
- if (SystemInfo.isUnix) {
- path = path.replace(SystemProperties.getUserHome(), "~");
- }
+ String path = FileUtil.getLocationRelativeToUserHome(guessedOldConfig.getAbsolutePath());
return ApplicationBundle.message("radio.import.auto", path);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
index bf7fe9c9652f..9f43164cf9d4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
@@ -20,7 +20,6 @@ import com.intellij.ide.DataManager;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.*;
@@ -96,11 +95,11 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
}
public static int getGlobalUndoLimit() {
- return Registry.intValue("undo.globalUndoLimit", 10);
+ return Registry.intValue("undo.globalUndoLimit");
}
public static int getDocumentUndoLimit() {
- return Registry.intValue("undo.documentUndoLimit", 100);
+ return Registry.intValue("undo.documentUndoLimit");
}
public UndoManagerImpl(Application application, CommandProcessor commandProcessor) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
index a916d9e5bb34..372b14efcfe6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
@@ -73,8 +73,9 @@ public class CompareClipboardWithSelection extends BaseDiffAction {
SelectionModel selectionModel = myEditor.getSelectionModel();
if (selectionModel.hasSelection()) {
TextRange range = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ boolean forceReadOnly = myEditor.isViewer();
myContents[1] = new FragmentContent(DiffContent.fromDocument(getProject(), getDocument()),
- range, getProject(), getDocumentFile(getDocument()));
+ range, getProject(), getDocumentFile(getDocument()), forceReadOnly);
}
else {
myContents [1] = DiffContent.fromDocument(getProject(), getDocument());
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 538058d2d190..ec7a316357e2 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
@@ -23,6 +23,8 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.DialogWrapperDialog;
import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -56,25 +58,26 @@ public class DiffPanelOptions {
myShowSourcePolicy = showSourcePolicy;
}
- public void showSource(OpenFileDescriptor descriptor) {
+ public void showSource(@Nullable OpenFileDescriptor descriptor) {
+ if (descriptor == null || myDiffPanel.getProject() == null) return;
myShowSourcePolicy.showSource(descriptor, myDiffPanel);
}
public interface ShowSourcePolicy {
- void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel);
+ void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel);
ShowSourcePolicy DONT_SHOW = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {}
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {}
};
ShowSourcePolicy OPEN_EDITOR = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
FileEditorManager.getInstance(diffPanel.getProject()).openTextEditor(descriptor, true);
}
};
ShowSourcePolicy OPEN_EDITOR_AND_CLOSE_DIFF = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
OPEN_EDITOR.showSource(descriptor, diffPanel);
if (diffPanel.getOwnerWindow() == null) return;
Disposer.dispose(diffPanel);
@@ -97,7 +100,7 @@ public class DiffPanelOptions {
};
ShowSourcePolicy DEFAULT = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
Window window = diffPanel.getOwnerWindow();
if (window == null) return;
else if (window instanceof Frame) OPEN_EDITOR.showSource(descriptor, diffPanel);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
index 5f169146145c..8ea3242d9361 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
@@ -73,7 +73,6 @@ import com.intellij.util.LineSeparator;
import com.intellij.util.containers.CacheOneStepIterator;
import com.intellij.util.diff.FilesTooBigForDiffException;
import com.intellij.util.ui.PlatformColors;
-import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -160,8 +159,8 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
myOwnerWindow = owner;
myIsSyncScroll = true;
final boolean v = !horizontal;
- myLeftSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, v ? 0 : 1, v ? 0 : 1));
- myRightSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), v ? 0 : 1, v ? 0 : 1, 1, 0));
+ myLeftSide = new DiffSideView(this, new CustomLineBorder(1, 0, v ? 0 : 1, v ? 0 : 1));
+ myRightSide = new DiffSideView(this, new CustomLineBorder(v ? 0 : 1, v ? 0 : 1, 1, 0));
myLeftSide.becomeMaster();
myDiffUpdater = new Rediffers(this);
@@ -298,13 +297,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
myData.setContents(content1, content2);
Project project = myData.getProject();
FileType[] types = DiffUtil.chooseContentTypes(new DiffContent[]{content1, content2});
- VirtualFile baseFile = content1.getFile();
- if (baseFile == null && myDiffRequest != null) {
- String path = myDiffRequest.getWindowTitle();
- if (path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
- }
- myLeftSide.setHighlighterFactory(createHighlighter(types[0], baseFile, project));
- myRightSide.setHighlighterFactory(createHighlighter(types[1], baseFile, project));
+ VirtualFile beforeFile = content1.getFile();
+ VirtualFile afterFile = content2.getFile();
+ String path = myDiffRequest == null ? null : myDiffRequest.getWindowTitle();
+ myLeftSide.setHighlighterFactory(createHighlighter(types[0], beforeFile, afterFile, path, project));
+ myRightSide.setHighlighterFactory(createHighlighter(types[1], afterFile, beforeFile, path, project));
setSplitterProportion(content1, content2);
rediff();
if (myIsRequestFocus) {
@@ -344,8 +341,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
}
}
// todo pay attention here
- private static DiffHighlighterFactory createHighlighter(FileType contentType, VirtualFile file, Project project) {
- return new DiffHighlighterFactoryImpl(contentType, file, project);
+ private static DiffHighlighterFactory createHighlighter(FileType contentType,
+ VirtualFile file,
+ VirtualFile otherFile,
+ String path,
+ Project project) {
+ VirtualFile baseFile = file;
+ if (baseFile == null) baseFile = otherFile;
+ if (baseFile == null && path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
+
+ return new DiffHighlighterFactoryImpl(contentType, baseFile, project);
}
void rediff() {
@@ -607,7 +612,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
return myData.getProject();
}
- public void showSource(OpenFileDescriptor descriptor) {
+ public void showSource(@Nullable OpenFileDescriptor descriptor) {
myOptions.showSource(descriptor);
}
@@ -1004,10 +1009,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
@Override
public void navigate(boolean requestFocus) {
- final OpenFileDescriptor descriptor = mySide.getCurrentOpenFileDescriptor();
- if (descriptor != null) {
- showSource(descriptor);
- }
+ showSource(mySide.getCurrentOpenFileDescriptor());
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
index 5f4507dcfad3..4b6a289d476e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.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,6 +19,7 @@ import com.intellij.openapi.diff.impl.highlighting.DiffPanelState;
import com.intellij.openapi.diff.impl.splitter.DiffDividerPaint;
import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Splitter;
import javax.swing.*;
@@ -43,8 +44,8 @@ class DiffSplitter extends Splitter implements DiffSplitterI {
setHonorComponentsMinimumSize(false);
}
- protected Splitter.Divider createDivider() {
- return new Divider(){
+ protected Divider createDivider() {
+ return new DividerImpl(){
public void paint(Graphics g) {
super.paint(g);
myPaint.paint(g, this);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
index 10362cc8b304..cbad541fe129 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
@@ -27,9 +27,7 @@ import com.intellij.openapi.diff.*;
import com.intellij.openapi.diff.actions.NextDiffAction;
import com.intellij.openapi.diff.actions.PreviousDiffAction;
import com.intellij.openapi.diff.actions.ToggleAutoScrollAction;
-import com.intellij.openapi.diff.impl.DiffUtil;
-import com.intellij.openapi.diff.impl.EditingSides;
-import com.intellij.openapi.diff.impl.GenericDataProvider;
+import com.intellij.openapi.diff.impl.*;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter;
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList;
@@ -49,16 +47,20 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorMarkupModel;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.LabeledComponent;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
-import com.intellij.util.diff.FilesTooBigForDiffException;
+import com.intellij.util.containers.Convertor;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -141,9 +143,6 @@ public class MergePanel2 implements DiffViewer {
private DiffRequest.ToolbarAddons createToolbar() {
return new DiffRequest.ToolbarAddons() {
public void customize(DiffToolbar toolbar) {
- ActionManager actionManager = ActionManager.getInstance();
- toolbar.addAction(actionManager.getAction(IdeActions.ACTION_COPY));
- toolbar.addAction(actionManager.getAction(IdeActions.ACTION_FIND));
toolbar.addAction(PreviousDiffAction.find());
toolbar.addAction(NextDiffAction.find());
toolbar.addSeparator();
@@ -235,6 +234,8 @@ public class MergePanel2 implements DiffViewer {
Editor base = getEditor(1);
Editor right = getEditor(2);
+ setupHighlighterSettings(left, base, right);
+
myMergeList.setMarkups(left, base, right);
EditingSides[] sides = {getFirstEditingSide(), getSecondEditingSide()};
myScrollSupport.install(sides);
@@ -271,6 +272,37 @@ public class MergePanel2 implements DiffViewer {
return myScrollSupport.isEnabled();
}
+ private void setupHighlighterSettings(Editor left, Editor base, Editor right) {
+ Editor[] editors = new Editor[]{left, base, right};
+ DiffContent[] contents = myData.getContents();
+ FileType[] types = DiffUtil.chooseContentTypes(contents);
+
+ VirtualFile fallbackFile = contents[1].getFile();
+ FileType fallbackType = contents[1].getContentType();
+
+ for (int i = 0; i < 3; i++) {
+ Editor editor = editors[i];
+ DiffContent content = contents[i];
+
+ EditorHighlighter highlighter =
+ createHighlighter(types[i], content.getFile(), fallbackFile, fallbackType, myData.getProject()).createHighlighter();
+ if (highlighter != null) {
+ ((EditorEx)editor).setHighlighter(highlighter);
+ }
+ }
+ }
+
+ private static DiffHighlighterFactory createHighlighter(FileType contentType,
+ VirtualFile file,
+ VirtualFile otherFile,
+ FileType otherType,
+ Project project) {
+ if (file == null) file = otherFile;
+ if (contentType == null) contentType = otherType;
+
+ return new DiffHighlighterFactoryImpl(contentType, file, project);
+ }
+
public void setHighlighterSettings(@Nullable EditorColorsScheme settings) {
for (EditorPlace place : getEditorPlaces()) {
setHighlighterSettings(settings, place);
@@ -337,7 +369,20 @@ public class MergePanel2 implements DiffViewer {
data.customizeToolbar(myPanel.resetToolbar());
myPanel.registerToolbarActions();
if ( data instanceof MergeRequestImpl && myBuilder != null){
- ((MergeRequestImpl)data).setActions(myBuilder, this);
+ Convertor<DialogWrapper, Boolean> preOkHook = new Convertor<DialogWrapper, Boolean>() {
+ @Override
+ public Boolean convert(DialogWrapper dialog) {
+ ChangeCounter counter = ChangeCounter.getOrCreate(myMergeList);
+ int changes = counter.getChangeCounter();
+ int conflicts = counter.getConflictCounter();
+ if (changes == 0 && conflicts == 0) return true;
+ return Messages.showYesNoDialog(dialog.getRootPane(),
+ DiffBundle.message("merge.dialog.apply.partially.resolved.changes.confirmation.message", changes, conflicts),
+ DiffBundle.message("apply.partially.resolved.merge.dialog.title"),
+ Messages.getQuestionIcon()) == Messages.YES;
+ }
+ };
+ ((MergeRequestImpl)data).setActions(myBuilder, this, preOkHook);
}
}
finally {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
index 3b13543e6972..962a0712465b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.diff.DiffRequestFactory;
import com.intellij.openapi.diff.MergeRequest;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -27,11 +28,11 @@ import org.jetbrains.annotations.Nullable;
public class DiffRequestFactoryImpl extends DiffRequestFactory {
- public MergeRequest createMergeRequest(String leftText,
- String rightText,
- String originalContent,
+ public MergeRequest createMergeRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
@NotNull VirtualFile file,
- Project project,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
final Document document = FileDocumentManager.getInstance().getDocument(file);
@@ -41,16 +42,26 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
cancelButtonPresentation);
}
else {
- return create3WayDiffRequest(leftText, rightText, originalContent, project, okButtonPresentation, cancelButtonPresentation);
+ return create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, okButtonPresentation, cancelButtonPresentation);
}
}
- public MergeRequest create3WayDiffRequest(final String leftText,
- final String rightText,
- final String originalContent,
- final Project project,
+ public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
+ @Nullable FileType type,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
- return new MergeRequestImpl(leftText, originalContent, rightText, project, okButtonPresentation, cancelButtonPresentation);
+ return new MergeRequestImpl(leftText, originalContent, rightText, type, project, okButtonPresentation, cancelButtonPresentation);
+ }
+
+ public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
+ @Nullable Project project,
+ @Nullable final ActionButtonPresentation okButtonPresentation,
+ @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+ return create3WayDiffRequest(leftText, rightText, originalContent, null, project, okButtonPresentation, cancelButtonPresentation);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
index 3b1385eb7a59..938c1ee7a42d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,39 +47,51 @@ public class MergeRequestImpl extends MergeRequest {
@Nullable private final ActionButtonPresentation myOkButtonPresentation;
@Nullable private final ActionButtonPresentation myCancelButtonPresentation;
- public MergeRequestImpl(String left,
- MergeVersion base,
- String right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull MergeVersion base,
+ @NotNull String right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
this(new SimpleContent(left), new MergeContent(base, project), new SimpleContent(right), project, okButtonPresentation,
cancelButtonPresentation);
}
- public MergeRequestImpl(DiffContent left,
- MergeVersion base,
- DiffContent right,
- Project project,
+ public MergeRequestImpl(@NotNull DiffContent left,
+ @NotNull MergeVersion base,
+ @NotNull DiffContent right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
this(left, new MergeContent(base, project), right, project, okButtonPresentation, cancelButtonPresentation);
}
- public MergeRequestImpl(String left,
- String base,
- String right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull String base,
+ @NotNull String right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
- this(new SimpleContent(left), new SimpleContent(base), new SimpleContent(right), project, okButtonPresentation,
- cancelButtonPresentation);
+ this(left, base, right, null, project, okButtonPresentation, cancelButtonPresentation);
}
- private MergeRequestImpl(DiffContent left,
- DiffContent base,
- DiffContent right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull String base,
+ @NotNull String right,
+ @Nullable FileType type,
+ @Nullable Project project,
+ @Nullable final ActionButtonPresentation okButtonPresentation,
+ @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+ this(new SimpleContent(left, type),
+ new SimpleContent(base, type),
+ new SimpleContent(right, type),
+ project, okButtonPresentation, cancelButtonPresentation);
+ }
+
+ private MergeRequestImpl(@NotNull DiffContent left,
+ @NotNull DiffContent base,
+ @NotNull DiffContent right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
super(project);
@@ -176,6 +189,10 @@ public class MergeRequestImpl extends MergeRequest {
}
public void setActions(final DialogBuilder builder, MergePanel2 mergePanel) {
+ setActions(builder, mergePanel, null);
+ }
+
+ public void setActions(final DialogBuilder builder, MergePanel2 mergePanel, final Convertor<DialogWrapper, Boolean> preOkHook) {
builder.removeAllActions(); // otherwise dialog will get default actions (OK, Cancel)
if (myOkButtonPresentation != null) {
@@ -187,6 +204,7 @@ public class MergeRequestImpl extends MergeRequest {
builder.setOkOperation(new Runnable() {
@Override
public void run() {
+ if (preOkHook != null && !preOkHook.convert(builder.getDialogWrapper())) return;
myOkButtonPresentation.run(builder.getDialogWrapper());
}
});
@@ -221,11 +239,11 @@ public class MergeRequestImpl extends MergeRequest {
}
public static class MergeContent extends DiffContent {
- private final MergeVersion myTarget;
+ @NotNull private final MergeVersion myTarget;
private final Document myWorkingDocument;
private final Project myProject;
- public MergeContent(MergeVersion target, Project project) {
+ public MergeContent(@NotNull MergeVersion target, Project project) {
myTarget = target;
myProject = project;
myWorkingDocument = myTarget.createWorkingDocument(project);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java b/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
new file mode 100644
index 000000000000..f0d2085cbb6b
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
@@ -0,0 +1,56 @@
+/*
+ * 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.editor;
+
+import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
+
+import java.awt.datatransfer.DataFlavor;
+
+public class CaretStateTransferableData implements TextBlockTransferableData {
+ public static final DataFlavor FLAVOR = new DataFlavor(CaretStateTransferableData.class, "Caret state");
+
+ public final int[] startOffsets;
+ public final int[] endOffsets;
+
+ public CaretStateTransferableData(int[] startOffsets, int[] endOffsets) {
+ this.startOffsets = startOffsets;
+ this.endOffsets = endOffsets;
+ }
+
+ @Override
+ public DataFlavor getFlavor() {
+ return FLAVOR;
+ }
+
+ @Override
+ public int getOffsetCount() {
+ return startOffsets.length + endOffsets.length;
+ }
+
+ @Override
+ public int getOffsets(int[] offsets, int index) {
+ System.arraycopy(startOffsets, 0, offsets, index, startOffsets.length);
+ System.arraycopy(endOffsets, 0, offsets, index + startOffsets.length, endOffsets.length);
+ return index + getOffsetCount();
+ }
+
+ @Override
+ public int setOffsets(int[] offsets, int index) {
+ System.arraycopy(offsets, index, startOffsets, 0, startOffsets.length);
+ System.arraycopy(offsets, index + startOffsets.length, endOffsets, 0, endOffsets.length);
+ return index + getOffsetCount();
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java b/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
new file mode 100644
index 000000000000..a3e62412f4a4
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.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.editor;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ClipboardTextPerCaretSplitter {
+ @NotNull
+ public List<String> split(@NotNull String input, @Nullable CaretStateTransferableData caretData, int caretCount) {
+ if (caretCount <= 0) {
+ throw new IllegalArgumentException("Caret count must be positive");
+ }
+ if (caretCount == 1) {
+ return Collections.singletonList(input);
+ }
+ List<String> result = new ArrayList<String>(caretCount);
+ int sourceCaretCount = caretData == null ? -1 : caretData.startOffsets.length;
+ String[] lines = sourceCaretCount == 1 || sourceCaretCount == caretCount ? null : input.split("\n", -1);
+ for (int i = 0; i < caretCount; i++) {
+ if (sourceCaretCount == 1) {
+ result.add(input);
+ }
+ else if (sourceCaretCount == caretCount) {
+ //noinspection ConstantConditions
+ result.add(new String(input.substring(caretData.startOffsets[i], caretData.endOffsets[i])));
+ }
+ else if (lines.length == 0) {
+ result.add("");
+ }
+ else if (lines.length == 1) {
+ result.add(lines[0]);
+ }
+ else if (lines.length % caretCount == 0) {
+ StringBuilder b = new StringBuilder();
+ int linesPerSegment = lines.length / caretCount;
+ for (int j = 0; j < linesPerSegment; j++) {
+ if (j > 0) {
+ b.append('\n');
+ }
+ b.append(lines[i * linesPerSegment + j]);
+ }
+ result.add(b.toString());
+ }
+ else {
+ result.add(i < lines.length ? lines[i] : "");
+ }
+ }
+ return result;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
index f8b3cf7bc83a..c42cd6533e1c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
@@ -15,31 +15,10 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
public class CloneCaretAbove extends EditorAction {
public CloneCaretAbove() {
- super(new Handler());
- }
-
- private static class Handler extends EditorActionHandler {
- public Handler() {
- super(true);
- }
-
- @Override
- public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
- caret.clone(true);
- }
-
- @Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return editor.getCaretModel().supportsMultipleCarets();
- }
+ super(new CloneCaretActionHandler(true));
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
new file mode 100644
index 000000000000..5c5528a38153
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
@@ -0,0 +1,113 @@
+/*
+ * 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.editor.actions;
+
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorLastActionTracker;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.util.Key;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+public class CloneCaretActionHandler extends EditorActionHandler {
+ private static final Key<Integer> LEVEL = Key.create("CloneCaretActionHandler.level");
+
+ private static final Set<String> OUR_ACTIONS = new HashSet<String>(Arrays.asList(
+ IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE,
+ IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW,
+ IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION,
+ IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION
+ ));
+
+ private final boolean myCloneAbove;
+
+ public CloneCaretActionHandler(boolean above) {
+ myCloneAbove = above;
+ }
+
+ @Override
+ public boolean isEnabled(Editor editor, DataContext dataContext) {
+ return editor.getCaretModel().supportsMultipleCarets();
+ }
+
+ @Override
+ protected void doExecute(Editor editor, @Nullable Caret targetCaret, DataContext dataContext) {
+ if (targetCaret != null) {
+ targetCaret.clone(myCloneAbove);
+ return;
+ }
+ int currentLevel = 0;
+ List<Caret> currentCarets = new ArrayList<Caret>();
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ int level = getLevel(caret);
+ if (Math.abs(level) > Math.abs(currentLevel)) {
+ currentLevel = level;
+ currentCarets.clear();
+ }
+ if (Math.abs(level) == Math.abs(currentLevel)) {
+ currentCarets.add(caret);
+ }
+ }
+ boolean removeCarets = currentLevel > 0 && myCloneAbove || currentLevel < 0 && !myCloneAbove;
+ Integer newLevel = myCloneAbove ? currentLevel - 1 : currentLevel + 1;
+ for (Caret caret : currentCarets) {
+ if (removeCarets) {
+ editor.getCaretModel().removeCaret(caret);
+ }
+ else {
+ Caret clone = caret;
+ do {
+ Caret original = clone;
+ clone = clone.clone(myCloneAbove);
+ if (original != caret) {
+ editor.getCaretModel().removeCaret(original);
+ }
+ } while (clone != null && caret.hasSelection() && !clone.hasSelection());
+ if (clone != null) {
+ clone.putUserData(LEVEL, newLevel);
+ }
+ }
+ }
+ if (removeCarets) {
+ editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ }
+ }
+
+ private static int getLevel(Caret caret) {
+ if (isRepeatedActionInvocation()) {
+ Integer value = caret.getUserData(LEVEL);
+ return value == null ? 0 : value;
+ }
+ else {
+ caret.putUserData(LEVEL, null);
+ return 0;
+ }
+ }
+
+ private static boolean isRepeatedActionInvocation() {
+ String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
+ return OUR_ACTIONS.contains(lastActionId);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
index 17d17708b900..974087796e08 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
@@ -15,35 +15,10 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
public class CloneCaretBelow extends EditorAction {
public CloneCaretBelow() {
- super(new Handler());
- }
-
- private static class Handler extends EditorActionHandler {
- public Handler() {
- super(true);
- }
-
- @Override
- public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
- CaretModel caretModel = editor.getCaretModel();
- if (caretModel.supportsMultipleCarets()) {
- caret.clone(false);
- }
- }
-
- @Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return editor.getCaretModel().supportsMultipleCarets();
- }
+ super(new CloneCaretActionHandler(false));
}
}
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 cfd039a5d504..c769f92fff78 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
@@ -62,7 +62,13 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
private int myVisualLineEnd;
private RangeMarker savedBeforeBulkCaretMarker;
private boolean mySkipChangeRequests;
+ /**
+ * Initial horizontal caret position during vertical navigation.
+ * Similar to {@link #myDesiredX}, but represents logical caret position (<code>getLogicalPosition().column</code>) rather than visual.
+ */
private int myLastColumnNumber = 0;
+ private int myDesiredSelectionStartColumn = -1;
+ private int myDesiredSelectionEndColumn = -1;
/**
* We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
* it's possible that the following situation occurs:
@@ -82,11 +88,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
*/
private boolean myReportCaretMoves;
/**
- * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
- * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
- * its initial visual position when possible.
+ * This field holds initial horizontal caret position during vertical navigation. It's used to determine target position when
+ * moving to the new line. It is stored in pixels, not in columns, to account for non-monospaced fonts as well.
* <p/>
- * This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
+ * Negative value means no coordinate should be preserved.
*/
private int myDesiredX = -1;
@@ -255,10 +260,11 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
EditorSettings editorSettings = myEditor.getSettings();
VisualPosition visualCaret = getVisualPosition();
+ int lastColumnNumber = myLastColumnNumber;
int desiredX = myDesiredX;
if (columnShift == 0) {
if (myDesiredX < 0) {
- desiredX = myEditor.visualPositionToXY(visualCaret).x;
+ desiredX = getCurrentX();
}
}
else {
@@ -267,15 +273,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
int newLineNumber = visualCaret.line + lineShift;
int newColumnNumber = visualCaret.column + columnShift;
- if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
+ if (desiredX >= 0) {
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
}
Document document = myEditor.getDocument();
- if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
- newColumnNumber = supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber();
- }
- else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
+ if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
int lastLine = document.getLineCount() - 1;
if (lastLine < 0) lastLine = 0;
if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
@@ -303,18 +306,21 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
// We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
newColumnNumber = 0;
desiredX = -1;
+ lastColumnNumber = -1;
}
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
- int lastColumnNumber = newColumnNumber;
if (!myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
int offset = myEditor.logicalPositionToOffset(log);
if (offset >= document.getTextLength()) {
int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
// We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
- newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
- desiredX = -1;
+ if (lastOffsetColumn > newColumnNumber) {
+ newColumnNumber = lastOffsetColumn;
+ desiredX = -1;
+ lastColumnNumber = -1;
+ }
}
if (!editorSettings.isCaretInsideTabs()) {
CharSequence text = document.getCharsSequence();
@@ -353,7 +359,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
else {
moveToVisualPosition(pos);
- if (!editorSettings.isVirtualSpace() && columnShift == 0) {
+ if (!editorSettings.isVirtualSpace() && columnShift == 0 && lastColumnNumber >=0) {
setLastColumnNumber(lastColumnNumber);
}
}
@@ -550,6 +556,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
setLastColumnNumber(myLogicalCaret.column);
+ myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
updateOffsetsFromLogicalPosition();
@@ -705,7 +712,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
myEditor.getFoldingModel().flushCaretPosition();
- setLastColumnNumber(column);
+ setLastColumnNumber(myLogicalCaret.column);
+ myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
myEditor.updateCaretCursor();
requestRepaint(oldInfo);
@@ -962,6 +970,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
clone.myLastColumnNumber = this.myLastColumnNumber;
clone.myReportCaretMoves = this.myReportCaretMoves;
clone.myDesiredX = this.myDesiredX;
+ clone.myDesiredSelectionStartColumn = -1;
+ clone.myDesiredSelectionEndColumn = -1;
return clone;
}
@@ -971,10 +981,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
assertIsDispatchThread();
int lineShift = above ? -1 : 1;
final CaretImpl clone = cloneWithoutSelection();
- final int newSelectionStartOffset, newSelectionEndOffset;
+ final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn;
final VisualPosition newSelectionStartPosition, newSelectionEndPosition;
final boolean hasNewSelection;
- if (hasSelection()) {
+ if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) {
VisualPosition startPosition = getSelectionStartPosition();
VisualPosition endPosition = getSelectionEndPosition();
VisualPosition leadPosition = getLeadSelectionPosition();
@@ -982,8 +992,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
boolean leadIsEnd = leadPosition.equals(endPosition);
LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition);
LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition);
- LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column));
- LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column));
+ newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn;
+ newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn;
+ LogicalPosition newSelectionStart = truncate(selectionStart.line + lineShift, newSelectionStartColumn);
+ LogicalPosition newSelectionEnd = truncate(selectionEnd.line + lineShift, newSelectionEndColumn);
newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart);
newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd);
newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart);
@@ -996,6 +1008,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
newSelectionStartPosition = null;
newSelectionEndPosition = null;
hasNewSelection = false;
+ newSelectionStartColumn = -1;
+ newSelectionEndColumn = -1;
}
LogicalPosition oldPosition = getLogicalPosition();
int newLine = oldPosition.line + lineShift;
@@ -1003,7 +1017,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
Disposer.dispose(clone);
return null;
}
- clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
+ clone.moveToLogicalPosition(new LogicalPosition(newLine, myLastColumnNumber), false, null, false);
+ clone.myLastColumnNumber = myLastColumnNumber;
+ clone.myDesiredX = myDesiredX >= 0 ? myDesiredX : getCurrentX();
+ clone.myDesiredSelectionStartColumn = newSelectionStartColumn;
+ clone.myDesiredSelectionEndColumn = newSelectionEndColumn;
+
if (myEditor.getCaretModel().addCaret(clone)) {
if (hasNewSelection) {
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
@@ -1025,15 +1044,15 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
}
- private LogicalPosition truncate(LogicalPosition position) {
- if (position.line < 0) {
+ private LogicalPosition truncate(int line, int column) {
+ if (line < 0) {
return new LogicalPosition(0, 0);
}
- else if (position.line >= myEditor.getDocument().getLineCount()) {
+ else if (line >= myEditor.getDocument().getLineCount()) {
return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength());
}
else {
- return position;
+ return new LogicalPosition(line, column);
}
}
@@ -1396,9 +1415,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
try {
- EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
- IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
- handler.execute(myEditor, myEditor.getDataContext());
+ EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
+ handler.execute(myEditor, CaretImpl.this, myEditor.getDataContext());
}
finally {
if (needOverrideSetting) {
@@ -1453,6 +1471,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
}
+ private int getCurrentX() {
+ return myEditor.visualPositionToXY(myVisibleCaret).x;
+ }
+
@Override
@NotNull
public EditorImpl getEditor() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
new file mode 100644
index 000000000000..c26c7e99ba63
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
@@ -0,0 +1,150 @@
+/*
+ * 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.editor.impl;
+
+import com.intellij.codeInsight.editorActions.TextBlockTransferable;
+import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.LineTokenizer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+public class EditorCopyPasteHelperImpl extends EditorCopyPasteHelper {
+ private static final Logger LOG = Logger.getInstance(EditorCopyPasteHelperImpl.class);
+
+ @Override
+ public void copySelectionToClipboard(@NotNull Editor editor) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ List<TextBlockTransferableData> extraData = new ArrayList<TextBlockTransferableData>();
+ String s = editor.getCaretModel().supportsMultipleCarets() ? getSelectedTextForClipboard(editor, extraData)
+ : editor.getSelectionModel().getSelectedText();
+ if (s == null) return;
+
+ s = TextBlockTransferable.convertLineSeparators(s, "\n", extraData);
+ Transferable contents = editor.getCaretModel().supportsMultipleCarets() ? new TextBlockTransferable(s, extraData, null) : new StringSelection(s);
+ CopyPasteManager.getInstance().setContents(contents);
+ }
+
+ public static String getSelectedTextForClipboard(@NotNull Editor editor, @NotNull Collection<TextBlockTransferableData> extraDataCollector) {
+ final StringBuilder buf = new StringBuilder();
+ String separator = "";
+ List<Caret> carets = editor.getCaretModel().getAllCarets();
+ int[] startOffsets = new int[carets.size()];
+ int[] endOffsets = new int[carets.size()];
+ for (int i = 0; i < carets.size(); i++) {
+ buf.append(separator);
+ String caretSelectedText = carets.get(i).getSelectedText();
+ startOffsets[i] = buf.length();
+ if (caretSelectedText != null) {
+ buf.append(caretSelectedText);
+ }
+ endOffsets[i] = buf.length();
+ separator = "\n";
+ }
+ extraDataCollector.add(new CaretStateTransferableData(startOffsets, endOffsets));
+ return buf.toString();
+ }
+
+ @Nullable
+ @Override
+ public TextRange[] pasteFromClipboard(@NotNull Editor editor) {
+ CopyPasteManager manager = CopyPasteManager.getInstance();
+ if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+ Transferable clipboardContents = manager.getContents();
+ if (clipboardContents != null) {
+ return pasteTransferable(editor, clipboardContents);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public TextRange[] pasteTransferable(final @NotNull Editor editor, @NotNull Transferable content) {
+ String text = getStringContent(content);
+ if (text == null) return null;
+
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ int caretCount = editor.getCaretModel().getCaretCount();
+ if (caretCount == 1 && editor.isColumnMode()) {
+ int pastedLineCount = LineTokenizer.calcLineCount(text, true);
+ EditorModificationUtil.deleteSelectedText(editor);
+ Caret caret = editor.getCaretModel().getPrimaryCaret();
+ for (int i = 0; i < pastedLineCount - 1; i++) {
+ caret = caret.clone(false);
+ if (caret == null) {
+ break;
+ }
+ }
+ caretCount = editor.getCaretModel().getCaretCount();
+ }
+ CaretStateTransferableData caretData = null;
+ try {
+ caretData = content.isDataFlavorSupported(CaretStateTransferableData.FLAVOR)
+ ? (CaretStateTransferableData)content.getTransferData(CaretStateTransferableData.FLAVOR) : null;
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ final TextRange[] ranges = new TextRange[caretCount];
+ final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretData, caretCount).iterator();
+ final int[] index = {0};
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ String segment = segments.next();
+ int caretOffset = caret.getOffset();
+ ranges[index[0]++] = new TextRange(caretOffset, caretOffset + segment.length());
+ EditorModificationUtil.insertStringAtCaret(editor, segment, false, true);
+ }
+ });
+ return ranges;
+ }
+ else {
+ int caretOffset = editor.getCaretModel().getOffset();
+ EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
+ return new TextRange[] { new TextRange(caretOffset, caretOffset + text.length())};
+ }
+ }
+
+ @Nullable
+ private static String getStringContent(@NotNull Transferable content) {
+ RawText raw = RawText.fromTransferable(content);
+ if (raw != null) return raw.rawText;
+
+ try {
+ return (String)content.getTransferData(DataFlavor.stringFlavor);
+ }
+ catch (UnsupportedFlavorException ignore) { }
+ catch (IOException ignore) { }
+
+ return null;
+ }
+}
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 f600c606a98d..39706f016adc 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
@@ -992,7 +992,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
}
public void setLineNumberAreaWidth(@NotNull TIntFunction calculator) {
- final int lineNumberAreaWidth = calculator.execute(myLineNumberConvertor.execute(endLineNumber()));
+ int maxLineNumber = 0;
+ for (int i = endLineNumber(); i >= 0; i--) {
+ int number = myLineNumberConvertor.execute(i);
+ if (number >= 0) {
+ maxLineNumber = number;
+ break;
+ }
+ }
+
+ final int lineNumberAreaWidth = calculator.execute(maxLineNumber);
if (myLineNumberAreaWidth != lineNumberAreaWidth) {
myLineNumberAreaWidth = lineNumberAreaWidth;
fireResized();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
index c1499a71a71b..8be2284e8360 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
@@ -15,10 +15,19 @@
*/
package com.intellij.openapi.editor.impl;
+import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
+import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,4 +64,28 @@ public class EditorHighlighterCache {
return null;
}
+ @Nullable
+ public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
+ EditorHighlighter highlighter = null;
+
+ PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
+ final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
+ final EditorHighlighter cachedEditorHighlighter;
+ boolean alreadyInitializedHighlighter = false;
+
+ if (document != null &&
+ (cachedEditorHighlighter = getEditorHighlighterForCachesBuilding(document)) != null &&
+ PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
+ highlighter = cachedEditorHighlighter;
+ alreadyInitializedHighlighter = true;
+ }
+ else if (virtualFile != null) {
+ highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
+ }
+
+ if (highlighter != null) {
+ return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
+ }
+ return null;
+ }
}
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 b708f38a9190..c0ffbd10aca4 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
@@ -33,7 +33,7 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.actionSystem.impl.MouseGestureManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.diagnostic.Logger;
@@ -147,7 +147,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@NotNull private final EditorComponentImpl myEditorComponent;
@NotNull private final EditorGutterComponentImpl myGutterComponent;
private final TraceableDisposable myTraceableDisposable = new TraceableDisposable(new Throwable());
- private volatile boolean hasTabs; // optimisation flag: when editor contains no tabs it is dramatically easier to calculate positions
static {
ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0, 0, UIManager.getFont("Label.font").getFamily()); // load costly font info
@@ -168,6 +167,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@NotNull private final CaretCursor myCaretCursor;
private final ScrollingTimer myScrollingTimer = new ScrollingTimer();
+ @SuppressWarnings("RedundantStringConstructorCall")
private final Object MOUSE_DRAGGED_GROUP = new String("MouseDraggedGroup");
@NotNull private final SettingsImpl mySettings;
@@ -246,8 +246,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@Nullable private Color myForcedBackground = null;
@Nullable private Dimension myPreferredSize;
private int myVirtualPageHeight;
- @Nullable private Runnable myGutterSizeUpdater = null;
- private boolean myGutterNeedsUpdate = false;
private Alarm myAppleRepaintAlarm;
private final Alarm myMouseSelectionStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@@ -317,8 +315,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
EditorImpl(@NotNull Document document, boolean viewer, @Nullable Project project) {
+ assertIsDispatchThread();
myProject = project;
myDocument = (DocumentEx)document;
+ if (myDocument instanceof DocumentImpl) {
+ ((DocumentImpl)myDocument).requestTabTracking();
+ }
myScheme = createBoundColorSchemeDelegate(null);
initTabPainter();
myIsViewer = viewer;
@@ -433,13 +435,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myPrimaryCaret != null) {
myPrimaryCaret.updateVisualPosition(); // repainting old primary caret's row background
}
- ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ updateCaretVisualPosition(e);
myPrimaryCaret = myCaretModel.getPrimaryCaret();
}
@Override
public void caretRemoved(CaretEvent e) {
- ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ updateCaretVisualPosition(e);
myPrimaryCaret = myCaretModel.getPrimaryCaret(); // repainting new primary caret's row background
myPrimaryCaret.updateVisualPosition();
}
@@ -548,7 +550,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
});
}
- updateHasTabsFlag(document.getImmutableCharSequence());
+ }
+
+ private static void updateCaretVisualPosition(CaretEvent e) {
+ CaretImpl caretImpl = ((CaretImpl)e.getCaret());
+ if (caretImpl != null) {
+ caretImpl.updateVisualPosition(); // repainting caret region
+ }
}
@NotNull
@@ -575,7 +583,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myPrefixWidthInPixels = 0;
if (myPrefixText != null) {
for (char c : myPrefixText) {
- myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+ LOG.assertTrue(myPrefixAttributes != null);
+ if (myPrefixAttributes != null) {
+ myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+ }
}
}
mySoftWrapModel.recalculate();
@@ -791,6 +802,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myConnection != null) {
myConnection.disconnect();
}
+ if (myDocument instanceof DocumentImpl) {
+ ((DocumentImpl)myDocument).giveUpTabTracking();
+ }
Disposer.dispose(myDisposable);
}
@@ -898,9 +912,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
new UiNotifyConnector(myEditorComponent, new Activatable.Adapter(){
@Override
public void showNotify() {
- if (myGutterNeedsUpdate) {
- updateGutterSize();
- }
+ myGutterComponent.updateSize();
}
});
@@ -1505,7 +1517,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private final int[] myLastXOffsets = new int[myLastStartOffsets.length];
private final int[] myLastXs = new int[myLastStartOffsets.length];
private int myCurrentCachePosition;
- private int myLastCacheHits, myTotalRequests; // todo remove
+ private int myLastCacheHits;
+ private int myTotalRequests; // todo remove
private int getTabbedTextWidth(int startOffset, int targetColumn, int xOffset) {
int x = xOffset;
@@ -1621,7 +1634,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@Override
public void repaint(final int startOffset, int endOffset) {
- if (!isShowing() || myScrollPane == null || myDocument.isInBulkUpdate()) {
+ if (!isShowing() || myDocument.isInBulkUpdate()) {
return;
}
@@ -1638,7 +1651,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private boolean isShowing() {
- return myGutterComponent != null && myGutterComponent.isShowing();
+ return myGutterComponent.isShowing();
}
private void repaintToScreenBottom(int startLine) {
@@ -1679,9 +1692,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void bulkUpdateFinished() {
- if (myScrollPane == null) {
- return;
- }
clearTextWidthCache();
@@ -1700,7 +1710,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (isStickySelection()) {
setStickySelection(false);
}
- if (myDocument.isInBulkUpdate() || myScrollingModel == null) {
+ if (myDocument.isInBulkUpdate()) {
// Assuming that the job is done at bulk listener callback methods.
return;
}
@@ -1716,7 +1726,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void changedUpdate(DocumentEvent e) {
- if (myScrollPane == null || myDocument.isInBulkUpdate()) return;
+ if (myDocument.isInBulkUpdate()) return;
clearTextWidthCache();
mySelectionModel.removeBlockSelection();
@@ -1754,16 +1764,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
Point caretLocation = visualPositionToXY(getCaretModel().getVisualPosition());
int scrollOffset = caretLocation.y - myCaretUpdateVShift;
getScrollingModel().scrollVertically(scrollOffset);
- updateHasTabsFlag(e.getNewFragment());
}
- private void updateHasTabsFlag(@NotNull CharSequence newChars) {
- if (!hasTabs) {
- hasTabs = StringUtil.contains(newChars, 0, newChars.length(), '\t');
- }
- }
public boolean hasTabs() {
- return hasTabs;
+ return !(myDocument instanceof DocumentImpl) || ((DocumentImpl)myDocument).mightContainTabs();
}
public boolean isScrollToCaret() {
@@ -1784,24 +1788,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void updateGutterSize() {
- if (myGutterSizeUpdater != null) return;
- myGutterSizeUpdater = new Runnable() {
+ LaterInvocator.invokeLater(new Runnable() {
@Override
public void run() {
- if (!isDisposed()) {
- if (isShowing()) {
- myGutterComponent.updateSize();
- myGutterNeedsUpdate = false;
- }
- else {
- myGutterNeedsUpdate = true;
- }
- }
- myGutterSizeUpdater = null;
+ myGutterComponent.updateSize();
}
- };
-
- SwingUtilities.invokeLater(myGutterSizeUpdater);
+ });
}
void validateSize() {
@@ -1945,7 +1937,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
if (isReleased) {
- g.setColor(new Color(128, 255, 128));
+ g.setColor(new JBColor(new Color(128, 255, 128), new Color(128, 255, 128)));
g.fillRect(clip.x, clip.y, clip.width, clip.height);
return;
}
@@ -2239,7 +2231,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myLastBackgroundColor = null;
int start = clipStartOffset;
- int end = clipEndOffset;
+
if (!myPurePaintingMode) {
getSoftWrapModel().registerSoftWrapsIfNecessary();
}
@@ -2250,7 +2242,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return;
}
- IterationState iterationState = new IterationState(this, start, end, isPaintSelection());
+ IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection());
TextAttributes attributes = iterationState.getMergedAttributes();
Color backColor = getBackgroundColor(attributes);
int fontType = attributes.getFontType();
@@ -2322,7 +2314,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
position.y += lineHeight;
start = lEnd;
}
- else if (collapsedFolderAt.getEndOffset() == end) {
+ else if (collapsedFolderAt.getEndOffset() == clipEndOffset) {
softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
if (softWrap != null) {
position.x = drawSoftWrapAwareBackground(
@@ -3677,19 +3669,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return logicalToVisualPosition(logicalPos, true);
}
- // TODO den remove as soon as the problem is fixed.
- private final ThreadLocal<Integer> stackDepth = new ThreadLocal<Integer>();
-
- // TODO den remove as soon as the problem is fixed.
@Override
@NotNull
public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
- stackDepth.set(0);
- return doLogicalToVisualPosition(logicalPos, softWrapAware);
+ return doLogicalToVisualPosition(logicalPos, softWrapAware,0);
}
@NotNull
- private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
+ private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware,
+ // TODO den remove as soon as the problem is fixed.
+ int stackDepth) {
assertReadAccess();
if (!myFoldingModel.isFoldingEnabled() && !mySoftWrapModel.isSoftWrappingEnabled()) {
return new VisualPosition(logicalPos.line, logicalPos.column);
@@ -3703,25 +3692,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
offset = outermostCollapsed.getStartOffset();
LogicalPosition foldStart = offsetToLogicalPosition(offset);
// TODO den remove as soon as the problem is fixed.
- Integer depth = stackDepth.get();
- if (depth >= 0) {
- stackDepth.set(depth + 1);
- if (depth > 15) {
- LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
- logicalPos + "'. State: " + dumpState());
- stackDepth.set(-1);
- }
- }
- // TODO den remove as soon as the problem is fixed.
- try {
- return doLogicalToVisualPosition(foldStart, true);
- }
- finally {
- depth = stackDepth.get();
- if (depth > 0) {
- stackDepth.set(depth - 1);
- }
+ if (stackDepth > 15) {
+ LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
+ logicalPos + "'. State: " + dumpState());
+ stackDepth = -1;
}
+ return doLogicalToVisualPosition(foldStart, true, stackDepth+1);
}
else {
offset = outermostCollapsed.getEndOffset() + 3; // WTF?
@@ -3988,7 +3964,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return false;
}
- if (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint())) {
+ if (myInitialMouseEvent!= null && (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint()))) {
myIgnoreMouseEventsConsecutiveToInitial = false;
myInitialMouseEvent = null;
return false;
@@ -4197,7 +4173,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
} else {
final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret;
- setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+ if (blockStart != null) {
+ setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+ }
}
}
else {
@@ -5002,7 +4980,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
void assertIsDispatchThread() {
- ApplicationManagerEx.getApplicationEx().assertIsDispatchThread();
+ ApplicationManager.getApplication().assertIsDispatchThread();
}
private static void assertReadAccess() {
@@ -5392,7 +5370,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public void run() {
int docLength = doc.getTextLength();
ProperTextRange range = composedTextRange.intersection(new TextRange(0, docLength));
- doc.deleteString(range.getStartOffset(), range.getEndOffset());
+ if (range != null) {
+ doc.deleteString(range.getStartOffset(), range.getEndOffset());
+ }
}
});
}
@@ -6745,7 +6725,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private class TablessBorder extends SideBorder {
private TablessBorder() {
- super(UIUtil.getBorderColor(), SideBorder.ALL);
+ super(JBColor.border(), SideBorder.ALL);
}
@Override
@@ -6769,7 +6749,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public Insets getBorderInsets(Component c) {
Container splitters = SwingUtilities.getAncestorOfClass(EditorsSplitters.class, c);
boolean thereIsSomethingAbove = !SystemInfo.isMac || UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR ||
- EditorImpl.this.myProject != null && !ToolWindowManagerEx.getInstanceEx(EditorImpl.this.myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
+ myProject != null && !ToolWindowManagerEx.getInstanceEx(myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0);
}
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 a2f45fe33857..6ec29e58dc0b 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
@@ -36,6 +36,7 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.ex.*;
import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
@@ -45,7 +46,7 @@ import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ProperTextRange;
-import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.ui.*;
@@ -428,7 +429,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void paint(Graphics g) {
+ public void paint(@NotNull Graphics g) {
((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
final Rectangle bounds = getBounds();
@@ -437,7 +438,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
errorIconBounds.y = bounds.height / 2 - errorIconBounds.height / 2;
try {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
g.setColor(getEditor().getColorsScheme().getDefaultBackground());
g.fillRect(0, 0, bounds.width, bounds.height);
@@ -493,7 +494,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void uninstallUI(JComponent c) {
+ public void uninstallUI(@NotNull JComponent c) {
super.uninstallUI(c);
myCachedTrack = null;
}
@@ -528,7 +529,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
@Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
super.paintThumb(g, c, thumbBounds);
return;
}
@@ -565,13 +566,13 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
@Override
protected int getThickness() {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) return super.getThickness();
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) return super.getThickness();
return super.getThickness() + (isMacOverlayScrollbar() ? 2 : 7);
}
@Override
protected void doPaintTrack(Graphics g, JComponent c, Rectangle bounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
g.setColor(getEditor().getColorsScheme().getDefaultBackground());
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
//return;
@@ -609,7 +610,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
private void paintTrackBasement(Graphics g, Rectangle bounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
+ g.setColor(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground());
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
return;
}
@@ -647,13 +650,13 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
private void drawMarkup(final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) {
final Queue<PositionedStripe> thinEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
@Override
- public int compare(PositionedStripe o1, PositionedStripe o2) {
+ public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
return o1.yEnd - o2.yEnd;
}
});
final Queue<PositionedStripe> wideEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
@Override
- public int compare(PositionedStripe o1, PositionedStripe o2) {
+ public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
return o1.yEnd - o2.yEnd;
}
});
@@ -757,12 +760,21 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
boolean drawBottomDecoration) {
int x = isMirrored() ? 3 : 5;
int paintWidth = width;
+ boolean flatStyle = Registry.is("ide.new.markup.markers");
if (thinErrorStripeMark) {
paintWidth /= 2;
- paintWidth += 1;
+ paintWidth += flatStyle ? 0 : 1;
x = isMirrored() ? width + 2 : 0;
}
if (color == null) return;
+ Color darker = UIUtil.isUnderDarcula()? color : ColorUtil.shift(color, 0.75);
+
+ if (flatStyle) {
+ g.setColor(darker);
+ g.fillRect(x, yStart, paintWidth, yEnd - yStart + 1);
+ return;
+ }
+
g.setColor(color);
g.fillRect(x + 1, yStart, paintWidth - 2, yEnd - yStart + 1);
@@ -774,7 +786,6 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
//top decoration
UIUtil.drawLine(g, x + 1, yStart, x + paintWidth - 2, yStart);
}
- Color darker = ColorUtil.shift(color, 0.75);
g.setColor(darker);
if (drawBottomDecoration) {
@@ -787,7 +798,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
// mouse events
@Override
- public void mouseClicked(final MouseEvent e) {
+ public void mouseClicked(@NotNull final MouseEvent e) {
CommandProcessor.getInstance().executeCommand(myEditor.getProject(), new Runnable() {
@Override
public void run() {
@@ -801,11 +812,11 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(@NotNull MouseEvent e) {
}
@Override
- public void mouseReleased(MouseEvent e) {
+ public void mouseReleased(@NotNull MouseEvent e) {
}
private int getWidth() {
@@ -824,7 +835,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(@NotNull MouseEvent e) {
EditorImpl.MyScrollBar scrollBar = myEditor.getVerticalScrollBar();
int buttonHeight = scrollBar.getDecScrollButtonHeight();
int lineCount = getDocument().getLineCount() + myEditor.getSettings().getAdditionalLinesCount();
@@ -897,16 +908,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mouseEntered(MouseEvent e) {
+ public void mouseEntered(@NotNull MouseEvent e) {
}
@Override
- public void mouseExited(MouseEvent e) {
+ public void mouseExited(@NotNull MouseEvent e) {
cancelMyToolTips(e, true);
}
@Override
- public void mouseDragged(MouseEvent e) {
+ public void mouseDragged(@NotNull MouseEvent e) {
cancelMyToolTips(e, true);
}
@@ -943,13 +954,15 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
public void markDirtied(@NotNull ProperTextRange yPositions) {
- int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
- int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
- : Math
- .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
- ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
+ if (myDirtyYPositions != WHOLE_DOCUMENT) {
+ int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
+ int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
+ : Math
+ .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
+ ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
- myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+ myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+ }
myEditorScrollbarTop = 0;
myEditorSourceHeight = 0;
@@ -1137,7 +1150,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
myHighlighters.add(rangeHighlighter);
}
Collections.sort(myHighlighters, new Comparator<RangeHighlighterEx>() {
- public int compare(RangeHighlighterEx ex1, RangeHighlighterEx ex2) {
+ public int compare(@NotNull RangeHighlighterEx ex1, @NotNull RangeHighlighterEx ex2) {
LogicalPosition startPos1 = myEditor.offsetToLogicalPosition(ex1.getAffectedAreaStartOffset());
LogicalPosition startPos2 = myEditor.offsetToLogicalPosition(ex2.getAffectedAreaStartOffset());
if (startPos1.line != startPos2.line) return 0;
@@ -1167,7 +1180,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
if (myVisualLine ==-1) return;
Dimension size = getPreferredSize();
EditorGutterComponentEx gutterComponentEx = myEditor.getGutterComponentEx();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
new file mode 100644
index 000000000000..5a9c704173aa
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
@@ -0,0 +1,323 @@
+/*
+ * 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.editor.impl;
+
+import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.LazyRangeMarkerFactory;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.WeakList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory {
+ private final Project myProject;
+ private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY");
+
+ public LazyRangeMarkerFactoryImpl(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
+ myProject = project;
+
+ EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
+ @Override
+ public void beforeDocumentChange(DocumentEvent e) {
+ transformRangeMarkers(e);
+ }
+
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ transformRangeMarkers(e);
+ }
+
+ private void transformRangeMarkers(@NotNull DocumentEvent e) {
+ Document document = e.getDocument();
+ VirtualFile file = fileDocumentManager.getFile(document);
+ if (file == null) {
+ return;
+ }
+
+ WeakList<LazyMarker> lazyMarkers = getMarkers(file);
+ if (lazyMarkers == null) {
+ return;
+ }
+
+ List<LazyMarker> markers = lazyMarkers.toStrongList();
+ for (LazyMarker marker : markers) {
+ if (file.equals(marker.getFile())) {
+ marker.getOrCreateDelegate();
+ }
+ }
+ }
+ }, project);
+ }
+
+ static WeakList<LazyMarker> getMarkers(@NotNull VirtualFile file) {
+ return file.getUserData(LazyRangeMarkerFactoryImpl.LAZY_MARKERS_KEY);
+ }
+
+ private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+ WeakList<LazyMarker> markers = getMarkers(file);
+
+ if (markers == null) {
+ markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
+ }
+ markers.add(marker);
+ }
+
+ private static void removeFromLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+ WeakList<LazyMarker> markers = getMarkers(file);
+
+ if (markers != null) {
+ markers.remove(marker);
+ }
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+ @Override
+ public RangeMarker compute() {
+ // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor
+ final LazyMarker marker = new OffsetLazyMarker(file, offset);
+ addToLazyMarkersList(marker, file);
+ return marker;
+ }
+ });
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+ @Override
+ public RangeMarker compute() {
+ final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
+ if (document != null) {
+ final int offset = calculateOffset(myProject, file, document, line, column);
+ return document.createRangeMarker(offset, offset, persistent);
+ }
+
+ final LazyMarker marker = new LineColumnLazyMarker(file, line, column);
+ addToLazyMarkersList(marker, file);
+ return marker;
+ }
+ });
+ }
+
+ abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker {
+ protected RangeMarker myDelegate; // the real range marker which is created only when document is opened, or (this) which means it's disposed
+ protected final VirtualFile myFile;
+ protected final int myInitialOffset;
+
+ private LazyMarker(@NotNull VirtualFile file, int offset) {
+ myFile = file;
+ myInitialOffset = offset;
+ }
+
+ boolean isDelegated() {
+ return myDelegate != null;
+ }
+
+ @NotNull
+ public VirtualFile getFile() {
+ return myFile;
+ }
+
+ @Nullable
+ protected final RangeMarker getOrCreateDelegate() {
+ if (myDelegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ if (document == null) {
+ return null;
+ }
+ myDelegate = createDelegate(myFile, document);
+ removeFromLazyMarkersList(this, myFile);
+ }
+ return isDisposed() ? null : myDelegate;
+ }
+
+ @Nullable
+ protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
+
+ @Override
+ @NotNull
+ public Document getDocument() {
+ RangeMarker delegate = getOrCreateDelegate();
+ if (delegate == null) {
+ //noinspection ConstantConditions
+ return FileDocumentManager.getInstance().getDocument(myFile);
+ }
+ return delegate.getDocument();
+ }
+
+ @Override
+ public int getStartOffset() {
+ return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getStartOffset();
+ }
+
+ public boolean isDisposed() {
+ return myDelegate == this;
+ }
+
+
+ @Override
+ public int getEndOffset() {
+ return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getEndOffset();
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = getOrCreateDelegate();
+ return delegate != null && !isDisposed() && delegate.isValid();
+ }
+
+ @Override
+ public void setGreedyToLeft(boolean greedy) {
+ getOrCreateDelegate().setGreedyToLeft(greedy);
+ }
+
+ @Override
+ public void setGreedyToRight(boolean greedy) {
+ getOrCreateDelegate().setGreedyToRight(greedy);
+ }
+
+ @Override
+ public boolean isGreedyToRight() {
+ return getOrCreateDelegate().isGreedyToRight();
+ }
+
+ @Override
+ public boolean isGreedyToLeft() {
+ return getOrCreateDelegate().isGreedyToLeft();
+ }
+
+ @Override
+ public void dispose() {
+ assert !isDisposed();
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ removeFromLazyMarkersList(this, myFile);
+ myDelegate = this; // mark of disposed marker
+ }
+ else {
+ delegate.dispose();
+ }
+ }
+ }
+
+ private static class OffsetLazyMarker extends LazyMarker {
+ private OffsetLazyMarker(@NotNull VirtualFile file, int offset) {
+ super(file, offset);
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ return document != null;
+ }
+
+ return super.isValid();
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
+ final int offset = Math.min(myInitialOffset, document.getTextLength());
+ return document.createRangeMarker(offset, offset);
+ }
+ }
+
+ private class LineColumnLazyMarker extends LazyMarker {
+ private final int myLine;
+ private final int myColumn;
+
+ private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) {
+ super(file, -1);
+ myLine = line;
+ myColumn = column;
+ }
+
+ @Override
+ @Nullable
+ public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
+ if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
+ return null;
+ }
+
+ int offset = calculateOffset(myProject, file, document, myLine, myColumn);
+ return document.createRangeMarker(offset, offset);
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ return document != null && (document.getTextLength() != 0 || myLine == 0 && myColumn == 0);
+ }
+
+ return super.isValid();
+ }
+
+ @Override
+ public int getStartOffset() {
+ getOrCreateDelegate();
+ return super.getStartOffset();
+ }
+
+ @Override
+ public int getEndOffset() {
+ getOrCreateDelegate();
+ return super.getEndOffset();
+ }
+ }
+
+ private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
+ int offset;
+ if (line < document.getLineCount()) {
+ final int lineStart = document.getLineStartOffset(line);
+ final int lineEnd = document.getLineEndOffset(line);
+ final CharSequence docText = document.getCharsSequence();
+ final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType());
+
+ offset = lineStart;
+ int col = 0;
+ while (offset < lineEnd && col < column) {
+ col += docText.charAt(offset) == '\t' ? tabSize : 1;
+ offset++;
+ }
+ }
+ else {
+ offset = document.getTextLength();
+ }
+ return offset;
+ }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
index 2f5a81153579..731d1e26a289 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
@@ -567,7 +567,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
@Override
public void copySelectionToClipboard() {
- CopyPasteSupport.copySelectionToClipboard(myEditor);
+ EditorCopyPasteHelper.getInstance().copySelectionToClipboard(myEditor);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
index 6f1b9820132b..d8b6697dc8d1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
@@ -303,14 +303,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
if (!isSoftWrappingEnabled()) {
return 0;
}
- int result = 0;
- FoldingModel foldingModel = myEditor.getFoldingModel();
- for (SoftWrap softWrap : myStorage.getSoftWraps()) {
- if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) {
- result++; // Assuming that soft wrap has single line feed all the time
- }
- }
- return result;
+ return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time
}
/**
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
index a5c477facfb3..165ff5776756 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.fileEditor.impl;
+package com.intellij.openapi.editor.impl;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.DocumentWindow;
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
-import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
import com.intellij.openapi.project.Project;
@@ -37,11 +36,12 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
-
public static final Key<String> OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY");
public static final Key<Boolean> OVERRIDE_ENSURE_NEWLINE_KEY = Key.create("OVERRIDE_ENSURE_NEWLINE_KEY");
@@ -61,7 +61,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
strip(document);
}
- private void strip(final Document document) {
+ private void strip(@NotNull final Document document) {
if (!document.isWritable()) return;
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
VirtualFile file = fileDocumentManager.getFile(document);
@@ -149,7 +149,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
((DocumentImpl)document).clearLineModificationFlagsExcept(caretLines);
}
- public static boolean stripIfNotCurrentLine(Document document, boolean inChangedLinesOnly) {
+ public static boolean stripIfNotCurrentLine(@NotNull Document document, boolean inChangedLinesOnly) {
if (document instanceof DocumentWindow) {
document = ((DocumentWindow)document).getDelegate();
}
@@ -168,10 +168,11 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
if (activeEditor != null && activeEditor.getCaretModel().supportsMultipleCarets()) {
List<Caret> carets = activeEditor.getCaretModel().getAllCarets();
List<VisualPosition> visualCarets = new ArrayList<VisualPosition>(carets.size());
- List<Integer> caretOffsets = new ArrayList<Integer>(carets.size());
- for (Caret caret : carets) {
+ int[] caretOffsets = new int[carets.size()];
+ for (int i = 0; i < carets.size(); i++) {
+ Caret caret = carets.get(i);
visualCarets.add(caret.getVisualPosition());
- caretOffsets.add(caret.getOffset());
+ caretOffsets[i] = caret.getOffset();
}
markAsNeedsStrippingLater = ((DocumentImpl)document).stripTrailingSpaces(activeEditor.getProject(), inChangedLinesOnly, isVirtualSpaceEnabled, caretOffsets);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
index c2353d5db207..03b03faffe03 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
@@ -277,6 +277,8 @@ public final class EditorTabbedContainer implements Disposable, CloseAction.Clos
myTabs.getTabAt(index).setTooltipText(text);
}
+ public boolean isTitleShortened(int index) { return myTabs.getTabAt(index).isTitleShortened(); }
+
public void setBackgroundColorAt(final int index, final Color color) {
myTabs.getTabAt(index).setTabColor(color);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
index 3519ab6a1af4..06a3966ade1d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.ui.ThreeComponentsSplitter;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -319,6 +320,16 @@ public class EditorWindow {
if (disposeIfNeeded && getTabCount() == 0) {
removeFromSplitter();
+ if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE) {
+ final EditorsSplitters owner = getOwner();
+ if (owner != null) {
+ final ThreeComponentsSplitter splitter = UIUtil.getParentOfType(ThreeComponentsSplitter.class, owner);
+ if (splitter != null) {
+ splitter.revalidate();
+ splitter.repaint();
+ }
+ }
+ }
}
else {
myPanel.revalidate();
@@ -453,6 +464,10 @@ public class EditorWindow {
}
}
+ private boolean isTitleShortenedAt(int index) {
+ return myTabbedPane != null && myTabbedPane.isTitleShortened(index);
+ }
+
private void setBackgroundColorAt(final int index, final Color color) {
if (myTabbedPane != null) {
myTabbedPane.setBackgroundColorAt(index, color);
@@ -897,7 +912,9 @@ public class EditorWindow {
final int index = findEditorIndex(findFileComposite(file));
if (index != -1) {
setTitleAt(index, EditorTabbedContainer.calcTabTitle(getManager().getProject(), file));
- setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS ? getManager().getFileTooltipText(file) : null);
+ setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS || isTitleShortenedAt(index)
+ ? getManager().getFileTooltipText(file)
+ : null);
}
}
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 f396b1eed399..091ff1171157 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
@@ -37,6 +37,7 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl;
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 e36a120d609b..c7fa51f770d1 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
@@ -227,7 +227,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
fm.doWhenFocusSettlesDown(run);
}
else {
- run.run();
+ UIUtil.invokeAndWaitIfNeeded(run);
}
return result;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
index 69a91ec31970..b19b2aa3e943 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.fileEditor.impl;
import com.intellij.ProjectTopics;
-import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.components.impl.stores.IProjectStore;
@@ -30,6 +29,7 @@ import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyKey;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.*;
import com.intellij.util.NotNullFunction;
import com.intellij.util.NullableFunction;
@@ -114,9 +114,7 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
if (deniedFiles.isEmpty()) return Collections.emptyList();
- final int savedEventCount = IdeEventQueue.getInstance().getEventCount();
UnlockOption unlockOption = askToUnlock(deniedFiles);
- IdeEventQueue.getInstance().setEventCount(savedEventCount);
if (unlockOption == null) return deniedFiles;
@@ -144,7 +142,9 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
}
private boolean isProjectFile(@NotNull VirtualFile file) {
- if (ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return true;
+ ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+ if (fileIndex.isInContent(file)) return true;
+ if (!Registry.is("ide.hide.excluded.files") && fileIndex.isExcluded(file) && !fileIndex.isUnderIgnored(file)) return true;
if (myProject instanceof ProjectEx) {
IProjectStore store = ((ProjectEx)myProject).getStateStore();
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 60b42f75c22c..690e7c7d2820 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
@@ -278,19 +278,22 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware {
}
protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
- if (editor.getCaretModel().supportsMultipleCarets()) {
- CaretModel caretModel = editor.getCaretModel();
- List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
- for (TextEditorState.CaretState caretState : state.CARETS) {
- states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
- new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
- new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+ if (state.CARETS != null) {
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ CaretModel caretModel = editor.getCaretModel();
+ List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
+ for (TextEditorState.CaretState caretState : state.CARETS) {
+ states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
+ new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
+ new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+ }
+ caretModel.setCaretsAndSelections(states);
+ }
+ else {
+ LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ editor.getSelectionModel().removeSelection();
}
- caretModel.setCaretsAndSelections(states);
- } else {
- LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
- editor.getCaretModel().moveToLogicalPosition(pos);
- editor.getSelectionModel().removeSelection();
}
EditorEx editorEx = editor instanceof EditorEx ? (EditorEx)editor : null;
boolean preciselyScrollVertically =
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
index 6c78ec12f9df..4b4d19136f01 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.impl.FocusManagerImpl;
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,6 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -230,12 +230,7 @@ public final class IdeMouseEventDispatcher {
}
private static void resetPopupTrigger(final MouseEvent e) {
- try {
- final Field popupTrigger = e.getClass().getDeclaredField("popupTrigger");
- popupTrigger.setAccessible(true);
- popupTrigger.set(e, false);
- }
- catch (Exception ignored) { }
+ ReflectionUtil.setField(MouseEvent.class, e, boolean.class, "popupTrigger", false);
}
/**
@@ -247,14 +242,7 @@ public final class IdeMouseEventDispatcher {
*/
public static boolean patchClickCount(final MouseEvent e) {
if (e.getClickCount() != 1 && e.getButton() > 3) {
- try {
- final Field clickCount = e.getClass().getDeclaredField("clickCount");
- clickCount.setAccessible(true);
- clickCount.set(e, 1);
- return true;
- }
- catch (Exception ignored) {
- }
+ ReflectionUtil.setField(MouseEvent.class, e, int.class, "clickCount", 1);
}
return false;
}
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 7b4f5a0371ba..7c65a805ee6c 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
@@ -99,8 +99,8 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat
if (Registry.is("editor.add.carets.on.double.control.arrows")) {
ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, KeyEvent.VK_CONTROL, KeyEvent.VK_UP);
ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, KeyEvent.VK_CONTROL, KeyEvent.VK_DOWN);
- ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
- ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
+ ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
+ ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
}
ourKeymapManagerInitialized = true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
index 28536453b713..13a8aaecb724 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
@@ -17,10 +17,10 @@ package com.intellij.openapi.keymap.impl;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeEventQueue;
-import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.Couple;
@@ -39,6 +39,10 @@ import java.util.concurrent.atomic.AtomicLong;
/**
* Support for keyboard shortcuts like Control-double-click or Control-double-click+A
+ *
+ * Timings that are used in the implementation to detect double click were tuned for SearchEverywhere
+ * functionality (invoked on double Shift), so if you need to change them, please make sure
+ * SearchEverywhere behaviour remains intact.
*/
public class ModifierKeyDoubleClickHandler {
private static final ModifierKeyDoubleClickHandler INSTANCE = new ModifierKeyDoubleClickHandler();
@@ -121,7 +125,7 @@ public class ModifierKeyDoubleClickHandler {
return false;
} else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get() && myActionKeyCode != -1) {
if (keyCode == myActionKeyCode) {
- if (event.getID() == KeyEvent.KEY_RELEASED) {
+ if (event.getID() == KeyEvent.KEY_PRESSED) {
run(keyEvent);
}
return true;
@@ -192,7 +196,7 @@ public class ModifierKeyDoubleClickHandler {
}
private void run(KeyEvent event) {
- final ActionManager actionManager = ActionManager.getInstance();
+ final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx();
final AnAction action = actionManager.getAction(myActionId);
final AnActionEvent anActionEvent = new AnActionEvent(event,
DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()),
@@ -200,7 +204,9 @@ public class ModifierKeyDoubleClickHandler {
action.getTemplatePresentation(),
actionManager,
0);
+ actionManager.fireBeforeActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
action.actionPerformed(anActionEvent);
+ actionManager.fireAfterActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
}
private boolean isActionBound() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
index b99f19242fa9..ebb3686969f0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
@@ -393,7 +393,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree()));
group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree()));
- group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.Actions.Properties) {
+ group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.ToolbarDecorator.Edit) {
{
registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), myActionsTree.getTree());
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
index 104dc7b30ec7..d7c7dca2f19b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
@@ -1,18 +1,64 @@
+/*
+ * 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
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
index e454099318ea..0ecb19a7ce8e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
@@ -1,3 +1,18 @@
+/*
+ * 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;
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
new file mode 100644
index 000000000000..9812165932a2
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
@@ -0,0 +1,52 @@
+/*
+ * 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/TabbedConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
index 35b75fe7c8d2..47d3881ee815 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
@@ -33,6 +33,7 @@ public abstract class TabbedConfigurable extends CompositeConfigurable<Configura
myParent = parent;
}
+ @Override
public JComponent createComponent() {
myTabbedPane = new TabbedPaneWrapper(myParent);
createConfigurableTabs();
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 6ee4a1b947ef..07e5a93670e6 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
@@ -36,6 +36,7 @@ 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.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.ui.DocumentAdapter;
@@ -366,6 +367,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myOwnDetails.setContent(myContentWrapper);
myOwnDetails.setBannerMinHeight(mySearchWrapper.getHeight());
myOwnDetails.setText(getBannerText(configurable));
+ if (Registry.is("ide.file.settings.order.new")) {
+ myOwnDetails.forProject(myTree.getConfigurableProject(configurable));
+ }
final ConfigurableContent content = myConfigurable2Content.get(current);
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 5524df2bb2cb..e0ab24815ece 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
@@ -308,7 +308,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
myHandle.setOpaque(false);
content.add(myHandle, BorderLayout.WEST);
content.add(myComponent, BorderLayout.CENTER);
- myProjectIcon = new JLabel(" ", AllIcons.General.ProjectConfigurable, SwingConstants.LEFT);
+ myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
myProjectIcon.setOpaque(true);
content.add(myProjectIcon, BorderLayout.EAST);
myRendererComponent.add(content, BorderLayout.CENTER);
@@ -407,32 +407,17 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
Project project = getConfigurableProject(base);
if (project != null && Registry.is("ide.file.settings.order.new")) {
myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground());
+ myProjectIcon.setIcon(selected ? AllIcons.General.ProjectConfigurableSelected : AllIcons.General.ProjectConfigurable);
myProjectIcon.setVisible(true);
- tree.setToolTipText(OptionsBundle.message(project.isDefault()
+ myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault()
? "configurable.default.project.tooltip"
: "configurable.current.project.tooltip"));
} else {
myProjectIcon.setVisible(false);
- tree.setToolTipText(null);
}
return result;
}
- private Project getConfigurableProject(SimpleNode node) {
- if (node == null) {
- return null;
- }
- if (node instanceof EditorNode) {
- EditorNode editor = (EditorNode)node;
- Configurable configurable = editor.getConfigurable();
- if (configurable instanceof ConfigurableWrapper) {
- ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
- return wrapper.getExtensionPoint().getProject();
- }
- }
- return getConfigurableProject(node.getParent());
- }
-
protected JComponent createItemComponent() {
myTextLabel = new ErrorLabel();
return myTextLabel;
@@ -642,6 +627,24 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
@Override
+ public final String getToolTipText(MouseEvent event) {
+ if (event != null) {
+ Point point = event.getPoint();
+ Component component = getDeepestRendererComponentAt(point.x, point.y);
+ if (component instanceof JLabel) {
+ JLabel label = (JLabel)component;
+ if (label.getIcon() != null) {
+ String text = label.getToolTipText();
+ if (text != null) {
+ return text;
+ }
+ }
+ }
+ }
+ return super.getToolTipText(event);
+ }
+
+ @Override
protected boolean paintNodes() {
return false;
}
@@ -877,4 +880,27 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
}
+
+ Project getConfigurableProject(Configurable configurable) {
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ return getConfigurableProject(myConfigurable2Node.get(configurable));
+ }
+
+ private static Project getConfigurableProject(SimpleNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (node instanceof EditorNode) {
+ EditorNode editor = (EditorNode)node;
+ Configurable configurable = editor.getConfigurable();
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ }
+ return getConfigurableProject(node.getParent());
+ }
}
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 a393d937dcfb..27bb8eb5f245 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
@@ -56,7 +56,10 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
private final ScheduledFuture<?> myCheckCancelledFuture;
public ProgressManagerImpl(Application application) {
- if (/*!application.isUnitTestMode() && */!DISABLED) {
+ if (DISABLED) {
+ myCheckCancelledFuture = null;
+ }
+ else {
myCheckCancelledFuture = JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
@@ -65,9 +68,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
- else {
- myCheckCancelledFuture = null;
- }
}
@Override
@@ -105,8 +105,8 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection {
private final ProgressIndicator myOld;
- private NonCancelableIndicator(ProgressIndicator old) {
- myOld = old;
+ private NonCancelableIndicator() {
+ myOld = myThreadIndicator.get();
}
@Override
@@ -124,16 +124,17 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
}
}
+ @NotNull
@Override
public final NonCancelableSection startNonCancelableSection() {
- NonCancelableIndicator nonCancelor = new NonCancelableIndicator(myThreadIndicator.get());
+ NonCancelableIndicator nonCancelor = new NonCancelableIndicator();
myThreadIndicator.set(nonCancelor);
return nonCancelor;
}
@Override
public void executeNonCancelableSection(@NotNull Runnable runnable) {
- executeProcessUnderProgress(runnable, new NonCancelableIndicator(getProgressIndicator()));
+ executeProcessUnderProgress(runnable, new NonCancelableIndicator());
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
index 6ffa084931b4..d1abc0816845 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
@@ -49,6 +49,7 @@ import com.intellij.ui.components.JBLayeredPane;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -59,7 +60,6 @@ import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -887,18 +887,12 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
if (rootPane != null) { // Workaround for bug in native code to hold rootPane
try {
- Field field = rootPane.getClass().getDeclaredField("glassPane");
- field.setAccessible(true);
- field.set(rootPane, null);
+ ReflectionUtil.resetField(rootPane.getClass(), null, "glassPane");
+ ReflectionUtil.resetField(rootPane.getClass(), null, "contentPane");
- field = rootPane.getClass().getDeclaredField("contentPane");
- field.setAccessible(true);
- field.set(rootPane, null);
rootPane = null;
- field = Window.class.getDeclaredField("windowListener");
- field.setAccessible(true);
- field.set(this, null);
+ ReflectionUtil.resetField(Window.class, null, "windowListener");
}
catch (Exception ignored) {
}
@@ -906,9 +900,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
// http://bugs.sun.com/view_bug.do?bug_id=6614056
try {
- final Field field = Dialog.class.getDeclaredField("modalDialogs");
- field.setAccessible(true);
- final List<?> list = (List<?>)field.get(null);
+ final List<?> list = ReflectionUtil.getField(Dialog.class, null, null, "modalDialogs");
list.remove(this);
}
catch (final Exception ignored) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
index 9dd3dd21f879..7e1c81ad2fbc 100755
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -618,12 +618,21 @@ public final class UpdateChecker {
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
try {
- URL requestUrl = new URL(url);
- if (!StandardFileSystems.FILE_PROTOCOL.equals(requestUrl.getProtocol())) {
- HttpConfigurable.getInstance().prepareURL(url);
- requestUrl = new URL(url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString());
+ final String urlToCheck;
+ if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
+ urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
+ } else {
+ urlToCheck = url;
}
- inputStreams[0] = requestUrl.openStream();
+
+ HttpURLConnection connection = ApplicationManager.getApplication() != null ?
+ HttpConfigurable.getInstance().openHttpConnection(urlToCheck) :
+ (HttpURLConnection)new URL(urlToCheck).openConnection();
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.connect();
+
+ inputStreams[0] = connection.getInputStream();
}
catch (IOException e) {
exception[0] = e;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
index 7177138d1d9a..a2d32fd1307f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
@@ -67,7 +67,9 @@ public abstract class HttpFileSystemBase extends HttpFileSystem {
@Override
@NotNull
public VirtualFile createChild(@NotNull VirtualFile parent, @NotNull String name, boolean isDirectory) {
- return getRemoteFileManager().getOrCreateFile((VirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + '/' + name), parent.getPath() + '/' + name, isDirectory);
+ String parentPath = parent.getPath();
+ boolean hasEndSlash = parentPath.charAt(parentPath.length() - 1) == '/';
+ return getRemoteFileManager().getOrCreateFile((HttpVirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + (hasEndSlash ? "" : '/') + name), parentPath + (hasEndSlash ? "" : '/') + name, isDirectory);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
index ba49cfb5a690..a8a1a447d66c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
@@ -35,7 +35,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
-class VirtualFileImpl extends HttpVirtualFile {
+class HttpVirtualFileImpl extends HttpVirtualFile {
private final HttpFileSystemBase myFileSystem;
@Nullable private final RemoteFileInfoImpl myFileInfo;
private FileType myInitialFileType;
@@ -45,7 +45,7 @@ class VirtualFileImpl extends HttpVirtualFile {
private List<VirtualFile> myChildren;
- VirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable VirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
+ HttpVirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable HttpVirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
if (parent != null) {
if (parent.myChildren == null) {
parent.myChildren = new SmartList<VirtualFile>();
@@ -63,7 +63,7 @@ class VirtualFileImpl extends HttpVirtualFile {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- VirtualFileImpl file = VirtualFileImpl.this;
+ HttpVirtualFileImpl file = HttpVirtualFileImpl.this;
FileDocumentManager.getInstance().reloadFiles(file);
if (!localFile.getFileType().equals(myInitialFileType)) {
FileContentUtilCore.reparseFiles(file);
@@ -135,8 +135,7 @@ class VirtualFileImpl extends HttpVirtualFile {
@Override
public VirtualFile getParent() {
- if (myParentPath == null) return null;
- return myFileSystem.findFileByPath(myParentPath, true);
+ return myParentPath == null ? null : myFileSystem.findFileByPath(myParentPath, true);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
index b69c0befd376..904233a35cdf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
@@ -17,7 +17,6 @@ package com.intellij.openapi.vfs.impl.http;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener;
import com.intellij.util.EventDispatcher;
@@ -35,7 +34,10 @@ import java.util.Map;
*/
public class RemoteFileManagerImpl extends RemoteFileManager implements Disposable {
private final LocalFileStorage myStorage;
- private final Map<Pair<Boolean, Url>, VirtualFileImpl> myRemoteFiles = new THashMap<Pair<Boolean, Url>, VirtualFileImpl>();
+
+ private final Map<Url, HttpVirtualFileImpl> remoteFiles = new THashMap<Url, HttpVirtualFileImpl>();
+ private final Map<Url, HttpVirtualFileImpl> remoteDirectories = new THashMap<Url, HttpVirtualFileImpl>();
+
private final EventDispatcher<HttpVirtualFileListener> myDispatcher = EventDispatcher.create(HttpVirtualFileListener.class);
private final List<RemoteContentProvider> myProviders = new ArrayList<RemoteContentProvider>();
private final DefaultRemoteContentProvider myDefaultRemoteContentProvider;
@@ -55,19 +57,19 @@ public class RemoteFileManagerImpl extends RemoteFileManager implements Disposab
return myDefaultRemoteContentProvider;
}
- public synchronized VirtualFileImpl getOrCreateFile(@Nullable VirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
- Pair<Boolean, Url> key = Pair.create(directory, url);
- VirtualFileImpl file = myRemoteFiles.get(key);
+ public synchronized HttpVirtualFileImpl getOrCreateFile(@Nullable HttpVirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
+ Map<Url, HttpVirtualFileImpl> cache = directory ? remoteDirectories : remoteFiles;
+ HttpVirtualFileImpl file = cache.get(url);
if (file == null) {
if (directory) {
- file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, null);
+ file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, null);
}
else {
RemoteFileInfoImpl fileInfo = new RemoteFileInfoImpl(url, this);
- file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
+ file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
fileInfo.addDownloadingListener(new MyDownloadingListener(file));
}
- myRemoteFiles.put(key, file);
+ cache.put(url, file);
}
return file;
}
@@ -133,9 +135,9 @@ public class RemoteFileManagerImpl extends RemoteFileManager implements Disposab
}
private class MyDownloadingListener extends FileDownloadingAdapter {
- private final VirtualFileImpl myFile;
+ private final HttpVirtualFileImpl myFile;
- public MyDownloadingListener(final VirtualFileImpl file) {
+ public MyDownloadingListener(final HttpVirtualFileImpl file) {
myFile = file;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
index efaf84d08b8e..98c3884cc993 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
@@ -30,6 +31,7 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.impl.ZipHandler;
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
+import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.IOUtil;
@@ -169,7 +171,6 @@ public class JarHandler extends ZipHandler {
info = new CacheLibraryInfo(mirrorFile.getName(), originalAttributes.lastModified, originalAttributes.length);
CacheLibraryInfo.ourCachedLibraryInfo.put(path, info);
- CacheLibraryInfo.ourCachedLibraryInfo.force();
return mirrorFile;
}
catch (IOException ex) {
@@ -260,6 +261,23 @@ public class JarHandler extends ZipHandler {
}
assert info != null;
ourCachedLibraryInfo = info;
+ FlushingDaemon.everyFiveSeconds(new Runnable() {
+ @Override
+ public void run() {
+ flushCachedLibraryInfos();
+ }
+ });
+
+ ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
+ @Override
+ public void run() {
+ flushCachedLibraryInfos();
+ }
+ });
+ }
+
+ private static void flushCachedLibraryInfos() {
+ if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force();
}
private CacheLibraryInfo(@NotNull String path, long time, long length) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
index ba44d2b21d10..2ecb28327857 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.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,17 +19,15 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
import com.intellij.openapi.fileEditor.impl.EditorWindowHolder;
import com.intellij.openapi.util.Computable;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
-import java.lang.reflect.Field;
public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy");
- @NonNls private static final String FOCUS_TRAVERSAL_POLICY_FIELD = "focusTraversalPolicy";
protected Component getDefaultComponentImpl(Container focusCycleRoot) {
if (!(focusCycleRoot instanceof JComponent)) {
@@ -103,15 +101,7 @@ public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt {
}
private static FocusTraversalPolicy getFocusTraversalPolicyAwtImpl(final JComponent component) {
- try {
- final Field field = Container.class.getDeclaredField(FOCUS_TRAVERSAL_POLICY_FIELD);
- field.setAccessible(true);
- return (FocusTraversalPolicy)field.get(component);
- }
- catch (Exception e) {
- LOG.error(e);
- return null;
- }
+ return ReflectionUtil.getField(Container.class, component, FocusTraversalPolicy.class, "focusTraversalPolicy");
}
protected final boolean accept(final Component aComponent) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
index 83696e07c7f8..71f964504102 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.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.
@@ -20,8 +20,9 @@ import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.dnd.DnDAware;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Painter;
-import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
@@ -42,6 +43,8 @@ import java.util.List;
public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEventQueue.EventDispatcher, Painter.Listener {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.IdeGlassPaneImpl");
+
private final List<EventListener> myMouseListeners = new ArrayList<EventListener>();
private final Set<EventListener> mySortedMouseListeners = new TreeSet<EventListener>(new Comparator<EventListener>() {
@Override
@@ -360,9 +363,12 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
}
else {
cursor = Cursor.getDefaultCursor();
- getRootPane().setCursor(cursor);
-
-
+ JRootPane rootPane = getRootPane();
+ if (rootPane != null) {
+ rootPane.setCursor(cursor);
+ } else {
+ LOG.warn("Root pane is null. Event: " + e);
+ }
restoreLastComponent(null);
myLastOriginalCursor = null;
myLastCursorComponent = null;
@@ -375,7 +381,7 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
private boolean canProcessCursorFor(Component target) {
if (target instanceof JMenu ||
target instanceof JMenuItem ||
- target instanceof Splitter.Divider ||
+ target instanceof Divider ||
target instanceof JSeparator ||
(target instanceof JEditorPane && ((JEditorPane)target).getEditorKit() instanceof HTMLEditorKit)) {
return false;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
index d6e1d9994500..8b78b1632f79 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
@@ -27,9 +27,11 @@ import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.*;
@@ -41,7 +43,7 @@ import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.ui.content.ContentManagerListener;
import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,12 +52,18 @@ import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.event.InputEvent;
import java.beans.PropertyChangeListener;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.*;
import java.util.List;
@SuppressWarnings({"ConstantConditions"})
public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
+ private final Map<String, ToolWindow> myToolWindows = new HashMap<String, ToolWindow>();
+ private final Project myProject;
+
+ public ToolWindowHeadlessManagerImpl(Project project) {
+ myProject = project;
+ }
+
@Override
public boolean canShowNotification(@NotNull String toolWindowId) {
return false;
@@ -65,7 +73,184 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) {
}
- public static final ToolWindow HEADLESS_WINDOW = new ToolWindowEx() {
+ private ToolWindow doRegisterToolWindow(final String id, @Nullable Disposable parentDisposable) {
+ MockToolWindow tw = new MockToolWindow(myProject);
+ myToolWindows.put(id, tw);
+ if (parentDisposable != null) {
+ Disposer.register(parentDisposable, new Disposable() {
+ @Override
+ public void dispose() {
+ unregisterToolWindow(id);
+ }
+ });
+ }
+ return tw;
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable,
+ boolean canWorkInDumbMode) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable,
+ boolean canWorkInDumbMode,
+ boolean canCloseContents) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id,
+ final boolean canCloseContent,
+ @NotNull final ToolWindowAnchor anchor,
+ final boolean secondary) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
+ final Disposable parentDisposable, final boolean dumbAware) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public void unregisterToolWindow(@NotNull String id) {
+ myToolWindows.remove(id);
+ }
+
+ @Override
+ public void activateEditorComponent() {
+ }
+
+ @Override
+ public boolean isEditorComponentActive() {
+ return false;
+ }
+
+ @Override
+ public String[] getToolWindowIds() {
+ return ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public String getActiveToolWindowId() {
+ return null;
+ }
+
+ @Override
+ public ToolWindow getToolWindow(String id) {
+ return myToolWindows.get(id);
+ }
+
+ @Override
+ public void invokeLater(Runnable runnable) {
+ }
+
+ @Override
+ public IdeFocusManager getFocusManager() {
+ return IdeFocusManagerHeadless.INSTANCE;
+ }
+
+ @Override
+ public void notifyByBalloon(@NotNull final String toolWindowId,
+ @NotNull final MessageType type,
+ @NotNull final String text,
+ @Nullable final Icon icon,
+ @Nullable final HyperlinkListener listener) {
+ }
+
+ @Override
+ public Balloon getToolWindowBalloon(String id) {
+ return null;
+ }
+
+ @Override
+ public void initToolWindow(ToolWindowEP bean) {
+
+ }
+
+ @Override
+ public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+
+ }
+
+ @Override
+ public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+ }
+
+ @Override
+ public String getLastActiveToolWindowId() {
+ return null;
+ }
+
+ @Override
+ public String getLastActiveToolWindowId(Condition<JComponent> condition) {
+ return null;
+ }
+
+ @Override
+ public DesktopLayout getLayout() {
+ return new DesktopLayout();
+ }
+
+ @Override
+ public void setLayoutToRestoreLater(DesktopLayout layout) {
+ }
+
+ @Override
+ public DesktopLayout getLayoutToRestoreLater() {
+ return new DesktopLayout();
+ }
+
+ @Override
+ public void setLayout(@NotNull DesktopLayout layout) {
+ }
+
+ @Override
+ public void clearSideStack() {
+ }
+
+ @Override
+ public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
+ }
+
+ @Override
+ public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
+ return new ArrayList<String>();
+ }
+
+ public static class MockToolWindow implements ToolWindowEx {
+ ContentManager myContentManager = new MockContentManager();
+
+ public MockToolWindow(@NotNull Project project) {
+ Disposer.register(project, myContentManager);
+ }
+
@Override
public boolean isActive() {
return false;
@@ -206,7 +391,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public ContentManager getContentManager() {
- return MOCK_CONTENT_MANAGER;
+ return myContentManager;
}
@Override
@@ -270,9 +455,9 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public boolean isUseLastFocusedOnActivation() {
return false;
}
- };
+ }
- @NonNls private static final ContentManager MOCK_CONTENT_MANAGER = new ContentManager() {
+ private static class MockContentManager implements ContentManager {
private final List<Content> myContents = new ArrayList<Content>();
private Content mySelected;
@@ -284,27 +469,33 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public void addContent(@NotNull final Content content) {
+ myContents.add(content);
+ if (mySelected == null) mySelected = content;
}
@Override
public void addContent(@NotNull Content content, int order) {
myContents.add(order, content);
+ if (mySelected == null) mySelected = content;
}
@Override
public void addContent(@NotNull final Content content, final Object constraints) {
+ addContent(content);
}
@Override
- public void addContentManagerListener(@NotNull final ContentManagerListener l) {
+ public void addSelectedContent(@NotNull final Content content) {
+ addContent(content);
+ setSelectedContent(content);
}
@Override
- public void addDataProvider(@NotNull final DataProvider provider) {
+ public void addContentManagerListener(@NotNull final ContentManagerListener l) {
}
@Override
- public void addSelectedContent(@NotNull final Content content) {
+ public void addDataProvider(@NotNull final DataProvider provider) {
}
@Override
@@ -319,6 +510,9 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public Content findContent(final String displayName) {
+ for (Content each : myContents) {
+ if (each.getDisplayName().equals(displayName)) return each;
+ }
return null;
}
@@ -359,18 +553,24 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public Content getContent(final JComponent component) {
+ Content[] contents = getContents();
+ for (Content content : contents) {
+ if (Comparing.equal(component, content.getComponent())) {
+ return content;
+ }
+ }
return null;
}
@Override
@Nullable
public Content getContent(final int index) {
- return null;
+ return myContents.get(index);
}
@Override
public int getContentCount() {
- return 0;
+ return myContents.size();
}
@Override
@@ -381,7 +581,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public int getIndexOfContent(final Content content) {
- return -1;
+ return myContents.indexOf(content);
}
@Override
@@ -393,35 +593,37 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
@NotNull
public Content[] getSelectedContents() {
- return new Content[0];
+ return mySelected != null ? new Content[]{mySelected} : new Content[0];
}
@Override
public boolean isSelected(@NotNull final Content content) {
- return false;
+ return content == mySelected;
}
@Override
public void removeAllContents(final boolean dispose) {
for (int i = myContents.size() - 1; i >= 0; i--) {
Content content = myContents.get(i);
- removeContent(content, true);
+ removeContent(content, dispose);
}
mySelected = null;
}
@Override
public boolean removeContent(@NotNull final Content content, final boolean dispose) {
- Disposer.dispose(content);
+ if (dispose) Disposer.dispose(content);
+ boolean result = myContents.remove(content);
if (mySelected == content) {
- mySelected = null;
+ mySelected = ContainerUtil.getFirstItem(myContents);
}
- return myContents.remove(content);
+ return result;
}
@NotNull
@Override
public ActionCallback removeContent(@NotNull Content content, boolean dispose, boolean trackFocus, boolean implicitFocus) {
+ removeContent(content, dispose);
return new ActionCallback.Done();
}
@@ -451,33 +653,36 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull Content content) {
+ setSelectedContent(content);
return new ActionCallback.Done();
}
@Override
public void setSelectedContent(@NotNull final Content content, final boolean requestFocus) {
+ setSelectedContent(content);
}
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@Override
public void setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus) {
+ setSelectedContent(content);
}
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus, final boolean forcedFocus) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@NotNull
@Override
public ActionCallback setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus, boolean implicit) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@NotNull
@@ -506,161 +711,4 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public ContentFactory getFactory() {
return ServiceManager.getService(ContentFactory.class);
}
- };
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable,
- boolean canWorkInDumbMode) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable,
- boolean canWorkInDumbMode,
- boolean canCloseContents) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id,
- final boolean canCloseContent,
- @NotNull final ToolWindowAnchor anchor,
- final boolean secondary) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
- final Disposable parentDisposable, final boolean dumbAware) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public void unregisterToolWindow(@NotNull String id) {
- }
-
- @Override
- public void activateEditorComponent() {
- }
-
- @Override
- public boolean isEditorComponentActive() {
- return false;
- }
-
- @Override
- public String[] getToolWindowIds() {
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String getActiveToolWindowId() {
- return null;
- }
-
- @Override
- public ToolWindow getToolWindow(String id) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public void invokeLater(Runnable runnable) {
- }
-
- @Override
- public IdeFocusManager getFocusManager() {
- return IdeFocusManagerHeadless.INSTANCE;
- }
-
- @Override
- public void notifyByBalloon(@NotNull final String toolWindowId,
- @NotNull final MessageType type,
- @NotNull final String text,
- @Nullable final Icon icon,
- @Nullable final HyperlinkListener listener) {
- }
-
- @Override
- public Balloon getToolWindowBalloon(String id) {
- return null;
- }
-
- @Override
- public void initToolWindow(ToolWindowEP bean) {
-
- }
-
- @Override
- public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
-
- }
-
- @Override
- public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
- }
-
- @Override
- public String getLastActiveToolWindowId() {
- return null;
- }
-
- @Override
- public String getLastActiveToolWindowId(Condition<JComponent> condition) {
- return null;
- }
-
- @Override
- public DesktopLayout getLayout() {
- return new DesktopLayout();
- }
-
- @Override
- public void setLayoutToRestoreLater(DesktopLayout layout) {
- }
-
- @Override
- public DesktopLayout getLayoutToRestoreLater() {
- return new DesktopLayout();
- }
-
- @Override
- public void setLayout(@NotNull DesktopLayout layout) {
- }
-
- @Override
- public void clearSideStack() {
- }
-
- @Override
- public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
- }
-
- @Override
- public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
- return new ArrayList<String>();
- }
-}
+ }}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
index 6c6bcd137949..120579bcb809 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.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.
@@ -16,9 +16,11 @@
package com.intellij.openapi.wm.impl;
import com.intellij.Patches;
+import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.diagnostic.Logger;
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.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +31,8 @@ import java.awt.*;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static com.intellij.util.ArrayUtil.newLongArray;
import static com.intellij.util.containers.ContainerUtil.newHashSet;
@@ -254,11 +258,17 @@ public class X11UiUtil {
setWM("MARCO_WM", "METACITY_WM");
}
else if ("awesome".equals(wmName)) {
- setWM("SAWFISH_WM");
+ String version = getAwesomeWMVersion();
+ if (StringUtil.compareVersionNumbers(version, "3.5") >= 0) {
+ setWM("SAWFISH_WM");
+ }
+ else if (version != null) {
+ setWM("OTHER_NONREPARENTING_WM", "LG3D_WM");
+ }
}
}
- catch (Throwable e) {
- LOG.warn(e);
+ catch (Throwable t) {
+ LOG.warn(t);
}
}
@@ -273,6 +283,7 @@ public class X11UiUtil {
if (id != null) {
field(xwmClass, "awt_wmgr").set(null, id);
field(xwmClass, "WMID").set(xwm, id);
+ LOG.info("impersonated WM: " + wmConstant);
break;
}
}
@@ -281,6 +292,23 @@ public class X11UiUtil {
}
}
+ @Nullable
+ private static String getAwesomeWMVersion() {
+ try {
+ String version = ExecUtil.execAndReadLine("awesome", "--version");
+ if (version != null) {
+ Matcher m = Pattern.compile("awesome v([0-9.]+)").matcher(version);
+ if (m.find()) {
+ return m.group(1);
+ }
+ }
+ }
+ catch (Throwable t) {
+ LOG.warn(t);
+ }
+ return null;
+ }
+
// full-screen support
public static boolean isFullScreenSupported() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
index 7a772e7aed34..2c681856a328 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.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.
@@ -19,11 +19,13 @@
*/
package com.intellij.openapi.wm.impl.commands;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Expirable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.impl.FloatingDecorator;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
@@ -44,10 +46,16 @@ public final class RequestFocusInEditorComponentCmd extends FinalizableCommand{
private final IdeFocusManager myFocusManager;
private final Expirable myTimestamp;
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInEditorComponentCmd");
+
public RequestFocusInEditorComponentCmd(@NotNull final EditorsSplitters splitters, IdeFocusManager
focusManager, final Runnable finishCallBack, boolean forced){
super(finishCallBack);
+ boolean shouldLogFocuses = Registry.is("ide.log.focuses");
+ if (shouldLogFocuses) {
+ LOG.info(new Exception());
+ }
myComponent = null;
final EditorWindow window = splitters.getCurrentWindow();
if (window != null) {
@@ -94,7 +102,8 @@ public final class RequestFocusInEditorComponentCmd extends FinalizableCommand{
}
if(myComponent != null){
- myFocusManager.requestFocus(myComponent, myForced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
+ final boolean forced = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == null;
+ myFocusManager.requestFocus(myComponent, myForced || forced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
public void run() {
// if owner is active window or it has active child window which isn't floating decorator then
// don't bring owner window to font. If we will make toFront every time then it's possible
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
index 9140fc200a77..82dba7430827 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.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.
@@ -186,14 +186,11 @@ public class RecentProjectPanel extends JPanel {
private String getTitle2Text(ReopenProjectAction action, JComponent pathLabel) {
String fullText = action.getProjectPath();
- int labelWidth = pathLabel.getWidth();
if (fullText == null || fullText.length() == 0) return " ";
- String home = SystemProperties.getUserHome();
- if (FileUtil.startsWith(fullText, home)) {
- fullText = "~" + fullText.substring(home.length());
- }
+ fullText = FileUtil.getLocationRelativeToUserHome(fullText, false);
+ int labelWidth = pathLabel.getWidth();
if (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) {
return myPathShortener.getShortPath(action);
}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
index e31b067e5d79..8d85ae106c44 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
@@ -116,11 +116,24 @@ public class RemoteConnectionCredentialsWrapper {
return new IllegalStateException("Unknown connection type"); //TODO
}
- public void copyTo(RemoteConnectionCredentialsWrapper copy) {
+ public void copyTo(final RemoteConnectionCredentialsWrapper copy) {
copy.myCredentialsTypeHolder = new UserDataHolderBase();
- copy.setPlainSshCredentials(getPlainSshCredentials());
- copy.setVagrantConnectionType(getVagrantCredentials());
- copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+ switchType(new RemoteSdkConnectionAcceptor() {
+ @Override
+ public void ssh(@NotNull RemoteCredentialsHolder cred) {
+ copy.setPlainSshCredentials(getPlainSshCredentials());
+ }
+
+ @Override
+ public void vagrant(@NotNull VagrantBasedCredentialsHolder cred) {
+ copy.setVagrantConnectionType(getVagrantCredentials());
+ }
+
+ @Override
+ public void deployment(@NotNull WebDeploymentCredentialsHolder cred) {
+ copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+ }
+ });
}
public String getId() {
diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
index a5ebae6fe567..9e2b60a54416 100644
--- a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
+++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,6 +44,10 @@ public abstract class VagrantSupport {
@NotNull
public abstract RemoteCredentials getVagrantSettings(@NotNull Project project, String vagrantFolder);
+ public abstract void getVagrantSettingsAsync(@Nullable Project project,
+ @NotNull String vagrantFolder,
+ @NotNull Consumer<RemoteCredentials> onSuccess);
+
@NotNull
public abstract RemoteCredentials getCredentials(@NotNull String folder) throws IOException;
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index 4e65063e7939..d8b204cfd76c 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -223,6 +223,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
if (selected == null
|| !myComponent.isEnabled()
|| !myComponent.isShowing()
+ || !myComponent.getVisibleRect().intersects(getVisibleRect(selected))
|| !myComponent.isFocusOwner() && !processIfUnfocused
|| isPopup()) {
hideHint();
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index 50a7ebbca92b..2a7d44d017bd 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.PlatformUtils;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -38,7 +39,6 @@ import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
-import java.lang.reflect.Field;
import java.net.URL;
import java.util.List;
import java.util.Locale;
@@ -111,9 +111,7 @@ public class AppUIUtil {
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Class<? extends Toolkit> aClass = toolkit.getClass();
if ("sun.awt.X11.XToolkit".equals(aClass.getName())) {
- final Field awtAppClassName = aClass.getDeclaredField("awtAppClassName");
- awtAppClassName.setAccessible(true);
- awtAppClassName.set(toolkit, getFrameClass());
+ ReflectionUtil.setField(aClass, toolkit, null, "awtAppClassName", getFrameClass());
}
}
catch (Exception ignore) { }
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index c6c209ed4b88..513d5cedb2ab 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
@@ -200,8 +200,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
if (cmp == myCloseRec) return true;
if (UIUtil.isDescendingFrom(cmp, myComp)) return true;
if (myComp == null || !myComp.isShowing()) return false;
- Rectangle rectangleOnScreen = new Rectangle(myComp.getLocationOnScreen(), myComp.getSize());
- return rectangleOnScreen.contains(target.getScreenPoint());
+ return myComp.contains(target.getScreenPoint().x, target.getScreenPoint().y);
}
public boolean isMovingForward(RelativePoint target) {
@@ -614,7 +613,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
myComp.setBorder(new EmptyBorder(borderSize, borderSize, borderSize, borderSize));
myLayeredPane.add(myComp);
- myLayeredPane.setLayer(myComp, getLayer());
+ myLayeredPane.setLayer(myComp, getLayer(), 0); // the second balloon must be over the first one
myPosition.updateBounds(this);
if (myBlockClicks) {
myComp.addMouseListener(new MouseAdapter() {
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
index c91be65978c1..1443a9303e39 100644
--- a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
@@ -15,8 +15,6 @@
*/
package com.intellij.ui;
-import java.awt.event.KeyEvent;
-
/**
* User: lex
* Date: Sep 18, 2003
@@ -56,11 +54,4 @@ public class CheckboxTree extends CheckboxTreeBase {
protected void installSpeedSearch() {
new TreeSpeedSearch(this);
}
-
-
- protected boolean isToggleEvent(KeyEvent e) {
- return super.isToggleEvent(e) && !SpeedSearchBase.hasActiveSpeedSearch(this);
- }
-
-
}
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
new file mode 100644
index 000000000000..369dd0cc1803
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 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.ui;
+
+import com.intellij.ui.dualView.TreeTableView;
+import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.EventDispatcher;
+import com.intellij.util.ui.ColumnInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class CheckboxTreeTable extends TreeTableView {
+ private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
+
+ public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
+ super(new ListTreeTableModelOnColumns(root, columns));
+ final TreeTableTree tree = getTree();
+ myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
+ CheckboxTreeHelper helper = new CheckboxTreeHelper(CheckboxTreeHelper.DEFAULT_POLICY, myEventDispatcher);
+ helper.initTree(tree, this, renderer);
+ tree.setSelectionRow(0);
+ }
+
+ public void addCheckboxTreeListener(@NotNull CheckboxTreeListener listener) {
+ myEventDispatcher.addListener(listener);
+ }
+
+ public <T> T[] getCheckedNodes(final Class<T> nodeType) {
+ return CheckboxTreeHelper.getCheckedNodes(nodeType, null, getTree().getModel());
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
index 39c8aaf41ace..d5fc8dcca1ba 100644
--- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.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.
@@ -20,7 +20,8 @@ import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.tabs.*;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
+import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,45 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants {
private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) {
- myTabs = new JBTabsImpl(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent);
+ myTabs = new JBEditorTabs(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent) {
+ @Override
+ public boolean isAlphabeticalMode() {
+ return false;
+ }
+
+ @Override
+ protected void doPaintBackground(Graphics2D g2d, Rectangle clip) {
+ super.doPaintBackground(g2d, clip);
+ if (getTabsPosition() == JBTabsPosition.top && isSingleRow()) {
+ int maxOffset = 0;
+ int maxLength = 0;
+
+ for (int i = getVisibleInfos().size() - 1; i >= 0; i--) {
+ TabInfo visibleInfo = getVisibleInfos().get(i);
+ TabLabel tabLabel = myInfo2Label.get(visibleInfo);
+ Rectangle r = tabLabel.getBounds();
+ if (r.width == 0 || r.height == 0) continue;
+ maxOffset = r.x + r.width;
+ maxLength = r.height;
+ break;
+ }
+
+ maxOffset++;
+ g2d.setPaint(UIUtil.getPanelBackground());
+ g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+ g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground()));
+ g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+ g2d.setPaint(UIUtil.getPanelBackground());
+ g2d.drawLine(clip.x, clip.y + maxLength, clip.width, clip.y + maxLength);
+ }
+ }
+
+ @Override
+ protected void paintSelectionAndBorder(Graphics2D g2d) {
+ super.paintSelectionAndBorder(g2d);
+ }
+ };
+
myTabs.addListener(new TabsListener.Adapter() {
@Override
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
diff --git a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
index 99c41b52cbea..e219b778f44d 100644
--- a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
+++ b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.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,6 +16,7 @@
package com.intellij.ui;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.PseudoSplitter;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.vcs.changes.RefreshablePanel;
@@ -41,7 +42,7 @@ public abstract class SplitterWithSecondHideable {
private final boolean myVertical;
private final OnOffListener<Integer> myListener;
private final JPanel myFictivePanel;
- private Splitter.Divider mySuperDivider;
+ private Splitter.DividerImpl mySuperDivider;
private float myPreviousProportion;
public SplitterWithSecondHideable(final boolean vertical,
@@ -185,7 +186,7 @@ public abstract class SplitterWithSecondHideable {
return vertical ? myTitledSeparator.getHeight() : myTitledSeparator.getWidth();
}
- class MyDivider extends Divider {
+ class MyDivider extends DividerImpl {
@Override
public void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
index 78802ccdf6bb..e50403abef45 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
@@ -162,6 +162,25 @@ public class AbstractPopup implements JBPopup {
private UiActivity myActivityKey;
private Disposable myProjectDisposable;
+ private volatile State myState = State.NEW;
+
+ private enum State {NEW, INIT, SHOWING, SHOWN, CANCEL, DISPOSE}
+
+ private void debugState(String message, State... states) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(hashCode() + " - " + message);
+ if (!ApplicationManager.getApplication().isDispatchThread()) {
+ LOG.debug("unexpected thread");
+ }
+ for (State state : states) {
+ if (state == myState) {
+ return;
+ }
+ }
+ LOG.debug(new IllegalStateException("myState=" + myState));
+ }
+ }
+
AbstractPopup() { }
AbstractPopup init(Project project,
@@ -302,6 +321,8 @@ public class AbstractPopup implements JBPopup {
}
myKeyEventHandler = keyEventHandler;
+ debugState("popup initialized", State.NEW);
+ myState = State.INIT;
return this;
}
@@ -582,10 +603,18 @@ public class AbstractPopup implements JBPopup {
@Override
public void cancel(InputEvent e) {
+ if (myState == State.CANCEL || myState == State.DISPOSE) {
+ return;
+ }
+ debugState("cancel popup", State.SHOWN);
+ myState = State.CANCEL;
+
if (isDisposed()) return;
if (myPopup != null) {
if (!canClose()) {
+ debugState("cannot cancel popup", State.CANCEL);
+ myState = State.SHOWN;
return;
}
storeDimensionSize(myContent.getSize());
@@ -610,8 +639,13 @@ public class AbstractPopup implements JBPopup {
}
if (myInStack) {
- myFocusTrackback.setForcedRestore(!myOk && myFocusable);
- myFocusTrackback.restoreFocus();
+ if (myFocusTrackback != null) {
+ myFocusTrackback.setForcedRestore(!myOk && myFocusable);
+ myFocusTrackback.restoreFocus();
+ }
+ else if (LOG.isDebugEnabled()) {
+ LOG.debug("cancel before show @ " + Thread.currentThread());
+ }
}
@@ -664,6 +698,9 @@ public class AbstractPopup implements JBPopup {
assert ApplicationManager.getApplication().isDispatchThread();
+ debugState("show popup", State.INIT);
+ myState = State.SHOWING;
+
installWindowHook(this);
installProjectDisposer();
addActivity();
@@ -673,6 +710,8 @@ public class AbstractPopup implements JBPopup {
final boolean shouldShow = beforeShow();
if (!shouldShow) {
removeActivity();
+ debugState("rejected to show popup", State.SHOWING);
+ myState = State.INIT;
return;
}
@@ -758,10 +797,11 @@ public class AbstractPopup implements JBPopup {
PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog);
myNativePopup = factory.isNativePopup();
Component popupOwner = myOwner;
- if (popupOwner instanceof RootPaneContainer) {
+ if (popupOwner instanceof RootPaneContainer && !(popupOwner instanceof IdeFrame && !Registry.is("popup.fix.ide.frame.owner"))) {
// JDK uses cached heavyweight popup for a window ancestor
RootPaneContainer root = (RootPaneContainer)popupOwner;
popupOwner = root.getRootPane();
+ LOG.debug("popup owner fixed for JDK cache");
}
if (LOG.isDebugEnabled()) {
LOG.debug("expected preferred size: " + myContent.getPreferredSize());
@@ -957,6 +997,8 @@ public class AbstractPopup implements JBPopup {
}
});
}
+ debugState("popup shown", State.SHOWING);
+ myState = State.SHOWN;
}
public void focusPreferredComponent() {
@@ -1232,6 +1274,16 @@ public class AbstractPopup implements JBPopup {
@Override
public void dispose() {
+ if (myState == State.SHOWN) {
+ LOG.debug("shown popup must be cancelled");
+ cancel();
+ }
+ if (myState == State.DISPOSE) {
+ return;
+ }
+ debugState("dispose popup", State.INIT, State.CANCEL);
+ myState = State.DISPOSE;
+
if (myDisposed) {
return;
}
@@ -1480,8 +1532,8 @@ public class AbstractPopup implements JBPopup {
@Override
public Dimension getSize() {
if (myPopup != null) {
- final Window popupWindow = SwingUtilities.windowForComponent(myContent);
- return popupWindow.getSize();
+ final Window popupWindow = getContentWindow(myContent);
+ return (popupWindow == null) ? myForcedSize : popupWindow.getSize();
} else {
return myForcedSize;
}
@@ -1491,7 +1543,8 @@ public class AbstractPopup implements JBPopup {
public void moveToFitScreen() {
if (myPopup == null) return;
- final Window popupWindow = SwingUtilities.windowForComponent(myContent);
+ final Window popupWindow = getContentWindow(myContent);
+ if (popupWindow == null) return;
Rectangle bounds = popupWindow.getBounds();
ScreenUtil.moveRectangleToFitTheScreen(bounds);
@@ -1501,7 +1554,8 @@ public class AbstractPopup implements JBPopup {
public static Window setSize(JComponent content, final Dimension size) {
- final Window popupWindow = SwingUtilities.windowForComponent(content);
+ final Window popupWindow = getContentWindow(content);
+ if (popupWindow == null) return null;
Insets insets = content.getInsets();
if (insets != null) {
size.width += insets.left + insets.right;
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
new file mode 100644
index 000000000000..2a79368f65bb
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
@@ -0,0 +1,35 @@
+/*
+ * 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.ui.popup;
+
+import com.intellij.openapi.util.registry.Registry;
+
+import javax.swing.Popup;
+import java.awt.Component;
+import java.awt.GraphicsEnvironment;
+
+/**
+ * @author Sergey Malenkov
+ */
+public final class OurHeavyWeightPopup extends Popup {
+ public OurHeavyWeightPopup(Component owner, Component content, int x, int y) {
+ super(owner, content, x, y);
+ }
+
+ public static boolean isEnabled() {
+ return !GraphicsEnvironment.isHeadless() && Registry.is("our.heavy.weight.popup");
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
index 301758511612..1670491b91bf 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.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.
@@ -58,6 +58,9 @@ public interface PopupComponent {
class AwtHeavyweight implements Factory {
public PopupComponent getPopup(Component owner, Component content, int x, int y, JBPopup jbPopup) {
+ if (OurHeavyWeightPopup.isEnabled()) {
+ return new AwtPopupWrapper(new OurHeavyWeightPopup(owner, content, x, y), jbPopup);
+ }
final PopupFactory factory = PopupFactory.getSharedInstance();
final int oldType = PopupUtil.getPopupType(factory);
@@ -172,7 +175,7 @@ public interface PopupComponent {
myJBPopup = jbPopup;
if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) {
- final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+ final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
c.setBackground(UIUtil.getPanelBackground());
}
}
@@ -220,7 +223,7 @@ public interface PopupComponent {
}
public Window getWindow() {
- final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+ final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
return c instanceof JWindow ? (JWindow)c : null;
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
index ac4c1b12373c..35719ca9366b 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
@@ -1,3 +1,18 @@
+/*
+ * 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.util.ui;
import com.intellij.ide.BrowserUtil;
@@ -48,7 +63,7 @@ public class SwingHelper {
* stacked vertically each on another in a given order.
*
* @param childAlignmentX Component.LEFT_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.RIGHT_ALIGNMENT
- * @param children children components
+ * @param children children components
* @return created panel
*/
@NotNull
@@ -76,7 +91,7 @@ public class SwingHelper {
* stacked each on another in a given order.
*
* @param childAlignmentY Component.TOP_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.BOTTOM_ALIGNMENT
- * @param children children components
+ * @param children children components
* @return created panel
*/
@NotNull
@@ -98,10 +113,11 @@ public class SwingHelper {
for (Component child : children) {
panel.add(child, childAlignment);
if (child instanceof JComponent) {
- JComponent jChild = (JComponent) child;
+ JComponent jChild = (JComponent)child;
if (verticalOrientation) {
jChild.setAlignmentX(childAlignment);
- } else {
+ }
+ else {
jChild.setAlignmentY(childAlignment);
}
}
@@ -259,20 +275,7 @@ public class SwingHelper {
textFieldWithHistory.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
- List<String> newHistory = historyProvider.produce();
- Set<String> newHistorySet = ContainerUtil.newHashSet(newHistory);
- List<String> oldHistory = textFieldWithHistory.getHistory();
- List<String> mergedHistory = ContainerUtil.newArrayList();
- for (String item : oldHistory) {
- if (!newHistorySet.contains(item)) {
- mergedHistory.add(item);
- }
- }
- mergedHistory.addAll(newHistory);
- textFieldWithHistory.setHistory(mergedHistory);
-
- setLongestAsPrototype(textFieldWithHistory, mergedHistory);
-
+ setHistory(textFieldWithHistory, historyProvider.produce(), true);
// one-time initialization
textFieldWithHistory.removePopupMenuListener(this);
}
@@ -287,11 +290,35 @@ public class SwingHelper {
});
}
+ public static void setHistory(@NotNull TextFieldWithHistory textFieldWithHistory,
+ @NotNull List<String> history,
+ boolean mergeWithPrevHistory) {
+ Set<String> newHistorySet = ContainerUtil.newHashSet(history);
+ List<String> prevHistory = textFieldWithHistory.getHistory();
+ List<String> mergedHistory = ContainerUtil.newArrayList();
+ if (mergeWithPrevHistory) {
+ for (String item : prevHistory) {
+ if (!newHistorySet.contains(item)) {
+ mergedHistory.add(item);
+ }
+ }
+ }
+ else {
+ String currentText = textFieldWithHistory.getText();
+ if (StringUtil.isNotEmpty(currentText) && !newHistorySet.contains(currentText)) {
+ mergedHistory.add(currentText);
+ }
+ }
+ mergedHistory.addAll(history);
+ textFieldWithHistory.setHistory(mergedHistory);
+ setLongestAsPrototype(textFieldWithHistory, mergedHistory);
+ }
+
private static void setLongestAsPrototype(@NotNull JComboBox comboBox, @NotNull List<String> variants) {
Object prototypeDisplayValue = comboBox.getPrototypeDisplayValue();
String prototypeDisplayValueStr = null;
if (prototypeDisplayValue instanceof String) {
- prototypeDisplayValueStr = (String) prototypeDisplayValue;
+ prototypeDisplayValueStr = (String)prototypeDisplayValue;
}
else if (prototypeDisplayValue != null) {
return;
@@ -413,15 +440,38 @@ public class SwingHelper {
return textPane;
}
- public static void setHtml(@NotNull JEditorPane editorPane, @NotNull String bodyInnerHtml) {
+ public static void setHtml(@NotNull JEditorPane editorPane,
+ @NotNull String bodyInnerHtml,
+ @Nullable Color foregroundColor) {
String html = String.format(
"<html><head>%s</head><body>%s</body></html>",
- UIUtil.getCssFontDeclaration(editorPane.getFont(), null, null, null),
+ UIUtil.getCssFontDeclaration(editorPane.getFont(), foregroundColor, null, null),
bodyInnerHtml
);
editorPane.setText(html);
}
+ @NotNull
+ public static TextFieldWithHistoryWithBrowseButton createTextFieldWithHistoryWithBrowseButton(@Nullable Project project,
+ @NotNull String browseDialogTitle,
+ @NotNull FileChooserDescriptor fileChooserDescriptor,
+ @Nullable NotNullProducer<List<String>> historyProvider) {
+ TextFieldWithHistoryWithBrowseButton textFieldWithHistoryWithBrowseButton = new TextFieldWithHistoryWithBrowseButton();
+ TextFieldWithHistory textFieldWithHistory = textFieldWithHistoryWithBrowseButton.getChildComponent();
+ textFieldWithHistory.setHistorySize(-1);
+ textFieldWithHistory.setMinimumAndPreferredWidth(0);
+ if (historyProvider != null) {
+ addHistoryOnExpansion(textFieldWithHistory, historyProvider);
+ }
+ installFileCompletionAndBrowseDialog(
+ project,
+ textFieldWithHistoryWithBrowseButton,
+ browseDialogTitle,
+ fileChooserDescriptor
+ );
+ return textFieldWithHistoryWithBrowseButton;
+ }
+
private static class CopyLinkAction extends AnAction {
private final String myUrl;