summaryrefslogtreecommitdiff
path: root/platform/platform-impl/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'platform/platform-impl/src/com')
-rw-r--r--platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java12
-rw-r--r--platform/platform-impl/src/com/intellij/designer/DesignerEditorPanelFacade.java (renamed from platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java)22
-rw-r--r--platform/platform-impl/src/com/intellij/designer/LightFillLayout.java122
-rw-r--r--platform/platform-impl/src/com/intellij/designer/LightToolWindow.java562
-rw-r--r--platform/platform-impl/src/com/intellij/designer/LightToolWindowContent.java23
-rw-r--r--platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java323
-rw-r--r--platform/platform-impl/src/com/intellij/designer/ToggleEditorModeAction.java60
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java118
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java94
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java175
-rw-r--r--platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java98
-rw-r--r--platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.java11
-rw-r--r--platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java326
-rw-r--r--platform/platform-impl/src/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java13
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ApplicationLoadListener.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java11
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/AssociateFileType.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java15
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ExitAction.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/OccurenceNavigatorActionBase.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java17
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SplitAction.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/Switcher.java83
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java14
-rw-r--r--platform/platform-impl/src/com/intellij/ide/dnd/aware/DnDAwareTree.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form8
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties1
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java88
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/ProjectPropertiesComponentImpl.java8
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/UsageTrigger.java9
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java6
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java6
-rw-r--r--platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java75
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java32
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java26
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/PluginPathManager.java44
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java8
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java36
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java44
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java95
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java134
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IApplicationStore.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java126
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java129
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java214
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java304
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java11
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java23
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorEmptyTextPainter.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java57
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java69
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java32
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java403
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java17
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java63
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java78
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java17
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java144
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java178
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java77
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/SortedConfigurableGroup.java195
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java44
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java305
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/ui/popup/MultiSelectionListPopupStep.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java29
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java67
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/CommandProcessor.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java201
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java3
-rw-r--r--platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java3
129 files changed, 3519 insertions, 2410 deletions
diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
index b33611da8866..876474b9124b 100644
--- a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
+++ b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
@@ -146,19 +146,11 @@ public class JobLauncherImpl extends JobLauncher {
// This implementation is not really async
@NotNull
@Override
- public <T> AsyncFutureResult<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<? extends T> things,
+ public <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<? extends T> things,
ProgressIndicator progress,
boolean failFastOnAcquireReadAction,
@NotNull Processor<T> thingProcessor) {
- final AsyncFutureResult<Boolean> asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult();
- try {
- final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor);
- asyncFutureResult.set(result);
- }
- catch (Throwable t) {
- asyncFutureResult.setException(t);
- }
- return asyncFutureResult;
+ return AsyncUtil.wrapBoolean(invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor));
}
@NotNull
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java b/platform/platform-impl/src/com/intellij/designer/DesignerEditorPanelFacade.java
index ff5d16361228..fa9ecf8610ac 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java
+++ b/platform/platform-impl/src/com/intellij/designer/DesignerEditorPanelFacade.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.
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.components.impl.stores;
+package com.intellij.designer;
-import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.openapi.ui.ThreeComponentsSplitter;
/**
- * @deprecated use {@link com.intellij.openapi.components.RoamingType#DISABLED}
+ * @author Alexander Lobas
*/
-@Deprecated
-public class RoamingTypeExtensionPointBean {
- @Attribute("component")
- public String componentName;
- @Attribute("type")
- public String roamingType;
-}
+public interface DesignerEditorPanelFacade {
+ Object getClientProperty(Object key);
+
+ void putClientProperty(Object key, Object value);
+
+ ThreeComponentsSplitter getContentSplitter();
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java b/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java
new file mode 100644
index 000000000000..af0ca87f1e05
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/designer/LightFillLayout.java
@@ -0,0 +1,122 @@
+/*
+ * 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.designer;
+
+import com.intellij.util.Function;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Alexander Lobas
+ */
+public class LightFillLayout implements LayoutManager2 {
+ @Override
+ public void addLayoutComponent(Component comp, Object constraints) {
+ }
+
+ @Override
+ public float getLayoutAlignmentX(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public float getLayoutAlignmentY(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public void invalidateLayout(Container target) {
+ }
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ }
+
+ @Override
+ public Dimension maximumLayoutSize(Container target) {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ return layoutSize(parent, new Function<Component, Dimension>() {
+ @Override
+ public Dimension fun(Component component) {
+ return component.getPreferredSize();
+ }
+ });
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return layoutSize(parent, new Function<Component, Dimension>() {
+ @Override
+ public Dimension fun(Component component) {
+ return component.getMinimumSize();
+ }
+ });
+ }
+
+ private static Dimension layoutSize(Container parent, Function<Component, Dimension> getSize) {
+ Component toolbar = parent.getComponent(0);
+ Dimension toolbarSize = toolbar.isVisible() ? getSize.fun(toolbar) : new Dimension();
+ Dimension contentSize = getSize.fun(parent.getComponent(1));
+ int extraWidth = 0;
+ JComponent jParent = (JComponent)parent;
+ if (jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY) != null) {
+ extraWidth += LightToolWindow.MINIMIZE_WIDTH;
+ }
+ if (jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY) != null) {
+ extraWidth += LightToolWindow.MINIMIZE_WIDTH;
+ }
+ return new Dimension(Math.max(toolbarSize.width, contentSize.width + extraWidth), toolbarSize.height + contentSize.height);
+ }
+
+ @Override
+ public void layoutContainer(Container parent) {
+ int leftWidth = 0;
+ int rightWidth = 0;
+ JComponent jParent = (JComponent)parent;
+ JComponent left = (JComponent)jParent.getClientProperty(LightToolWindow.LEFT_MIN_KEY);
+ if (left != null) {
+ leftWidth = LightToolWindow.MINIMIZE_WIDTH;
+ }
+ JComponent right = (JComponent)jParent.getClientProperty(LightToolWindow.RIGHT_MIN_KEY);
+ if (right != null) {
+ rightWidth = LightToolWindow.MINIMIZE_WIDTH;
+ }
+ int extraWidth = leftWidth + rightWidth;
+
+ int width = parent.getWidth() - extraWidth;
+ int height = parent.getHeight();
+ Component toolbar = parent.getComponent(0);
+ Dimension toolbarSize = toolbar.isVisible() ? toolbar.getPreferredSize() : new Dimension();
+ toolbar.setBounds(leftWidth, 0, width, toolbarSize.height);
+ parent.getComponent(1).setBounds(leftWidth, toolbarSize.height, width, height - toolbarSize.height);
+
+ if (left != null) {
+ left.setBounds(0, 0, leftWidth, height);
+ }
+ if (right != null) {
+ right.setBounds(width + leftWidth, 0, rightWidth, height);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java
new file mode 100644
index 000000000000..ce3cb33deb90
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
+import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory;
+import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ThreeComponentsSplitter;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.wm.*;
+import com.intellij.openapi.wm.ex.ToolWindowEx;
+import com.intellij.openapi.wm.impl.AnchoredButton;
+import com.intellij.openapi.wm.impl.InternalDecorator;
+import com.intellij.openapi.wm.impl.StripeButtonUI;
+import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
+import com.intellij.ui.*;
+import com.intellij.ui.components.panels.Wrapper;
+import com.intellij.ui.tabs.TabsUtil;
+import com.intellij.util.ui.EmptyIcon;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.BufferedImage;
+
+/**
+ * @author Alexander Lobas
+ */
+public class LightToolWindow extends JPanel {
+ public static final String LEFT_MIN_KEY = "left";
+ public static final String RIGHT_MIN_KEY = "right";
+ public static final int MINIMIZE_WIDTH = 25;
+ private static final String IGNORE_WIDTH_KEY = "ignore_width";
+
+ private final LightToolWindowContent myContent;
+ private final JComponent myFocusedComponent;
+ private final ThreeComponentsSplitter myContentSplitter;
+ private ToolWindowAnchor myAnchor;
+ private final Project myProject;
+ private final LightToolWindowManager myManager;
+ private final PropertiesComponent myPropertiesComponent;
+ private boolean myShowContent;
+ private final String myShowStateKey;
+ private int myCurrentWidth;
+ private final String myWidthKey;
+ private final JPanel myMinimizeComponent;
+ private final AnchoredButton myMinimizeButton;
+
+ private final TogglePinnedModeAction myToggleAutoHideModeAction = new TogglePinnedModeAction();
+ private final ToggleDockModeAction myToggleDockModeAction = new ToggleDockModeAction();
+ private final ToggleFloatingModeAction myToggleFloatingModeAction = new ToggleFloatingModeAction();
+ private final ToggleSideModeAction myToggleSideModeAction = new ToggleSideModeAction();
+
+ private final ComponentListener myWidthListener = new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ int width = isLeft() ? myContentSplitter.getFirstSize() : myContentSplitter.getLastSize();
+ if (width > 0 && width != myCurrentWidth && myContentSplitter.getInnerComponent().getClientProperty(IGNORE_WIDTH_KEY) == null) {
+ myCurrentWidth = width;
+ myPropertiesComponent.setValue(myWidthKey, Integer.toString(width));
+ }
+ }
+ };
+
+ public LightToolWindow(@NotNull LightToolWindowContent content,
+ @NotNull String title,
+ @NotNull Icon icon,
+ @NotNull JComponent component,
+ @NotNull JComponent focusedComponent,
+ @NotNull ThreeComponentsSplitter contentSplitter,
+ @Nullable ToolWindowAnchor anchor,
+ @NotNull LightToolWindowManager manager,
+ @NotNull Project project,
+ @NotNull PropertiesComponent propertiesComponent,
+ @NotNull String key,
+ int defaultWidth,
+ @Nullable AnAction[] actions) {
+ super(new BorderLayout());
+ myContent = content;
+ myFocusedComponent = focusedComponent;
+ myContentSplitter = contentSplitter;
+ myAnchor = anchor;
+ myProject = project;
+ myManager = manager;
+ myPropertiesComponent = propertiesComponent;
+
+ myShowStateKey = LightToolWindowManager.EDITOR_MODE + key + ".SHOW";
+ myWidthKey = LightToolWindowManager.EDITOR_MODE + key + ".WIDTH";
+
+ HeaderPanel header = new HeaderPanel();
+ header.setLayout(new BorderLayout());
+ add(header, BorderLayout.NORTH);
+
+ JLabel titleLabel = new JLabel(title);
+ titleLabel.setBorder(IdeBorderFactory.createEmptyBorder(2, 5, 2, 10));
+ titleLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
+ header.add(titleLabel, BorderLayout.CENTER);
+
+ JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
+ actionPanel.setBorder(IdeBorderFactory.createEmptyBorder(3, 0, 2, 0));
+ actionPanel.setOpaque(false);
+ header.add(actionPanel, BorderLayout.EAST);
+
+ if (actions != null) {
+ for (AnAction action : actions) {
+ addAction(actionPanel, action);
+ }
+
+ actionPanel.add(new JLabel(AllIcons.General.Divider));
+ }
+
+ addAction(actionPanel, new GearAction());
+ addAction(actionPanel, new HideAction());
+
+ JPanel contentWrapper = new JPanel(new BorderLayout());
+ contentWrapper.setBorder(IdeBorderFactory.createBorder(SideBorder.TOP));
+ contentWrapper.add(component, BorderLayout.CENTER);
+
+ add(contentWrapper, BorderLayout.CENTER);
+
+ addMouseListener(new MouseAdapter() {
+ public void mouseReleased(final MouseEvent e) {
+ IdeFocusManager.getInstance(myProject).requestFocus(myFocusedComponent, true);
+ }
+ });
+
+ addMouseListener(new PopupHandler() {
+ public void invokePopup(Component component, int x, int y) {
+ showGearPopup(component, x, y);
+ }
+ });
+
+ myMinimizeButton = new AnchoredButton(title, icon) {
+ @Override
+ public void updateUI() {
+ setUI(StripeButtonUI.createUI(this));
+ setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
+ }
+
+ @Override
+ public int getMnemonic2() {
+ return 0;
+ }
+
+ @Override
+ public ToolWindowAnchor getAnchor() {
+ return myAnchor;
+ }
+ };
+ myMinimizeButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myMinimizeButton.setSelected(false);
+ updateContent(true, true);
+ }
+ });
+ myMinimizeButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5));
+ myMinimizeButton.setFocusable(false);
+
+ myMinimizeButton.setRolloverEnabled(true);
+ myMinimizeButton.setOpaque(false);
+
+ myMinimizeComponent = new JPanel() {
+ @Override
+ public void doLayout() {
+ Dimension size = myMinimizeButton.getPreferredSize();
+ myMinimizeButton.setBounds(0, 0, getWidth(), size.height);
+ }
+ };
+ myMinimizeComponent.add(myMinimizeButton);
+
+ configureBorder();
+ configureWidth(defaultWidth);
+ updateContent(myPropertiesComponent.getBoolean(myShowStateKey, true), false);
+ }
+
+ private void configureBorder() {
+ int borderStyle = isLeft() ? SideBorder.RIGHT : SideBorder.LEFT;
+ setBorder(IdeBorderFactory.createBorder(borderStyle));
+ myMinimizeComponent.setBorder(IdeBorderFactory.createBorder(borderStyle));
+ }
+
+ private void configureWidth(int defaultWidth) {
+ myCurrentWidth = myPropertiesComponent.getOrInitInt(myWidthKey, defaultWidth);
+ updateWidth();
+ myContentSplitter.getInnerComponent().addComponentListener(myWidthListener);
+ }
+
+ private void updateWidth() {
+ if (isLeft()) {
+ myContentSplitter.setFirstSize(myCurrentWidth);
+ }
+ else {
+ myContentSplitter.setLastSize(myCurrentWidth);
+ }
+ }
+
+ public void updateAnchor(ToolWindowAnchor newAnchor) {
+ JComponent minimizeParent = myContentSplitter.getInnerComponent();
+ minimizeParent.putClientProperty(IGNORE_WIDTH_KEY, Boolean.TRUE);
+
+ if (myShowContent) {
+ Object oldWindow = isLeft() ? myContentSplitter.getFirstComponent() : myContentSplitter.getLastComponent();
+ if (oldWindow == this) {
+ setContentComponent(null);
+ }
+ }
+ else {
+ String key = getMinKey();
+ if (minimizeParent.getClientProperty(key) == myMinimizeComponent) {
+ minimizeParent.putClientProperty(key, null);
+ }
+ minimizeParent.putClientProperty(isLeft() ? RIGHT_MIN_KEY : LEFT_MIN_KEY, myMinimizeComponent);
+ minimizeParent.revalidate();
+ }
+
+ myAnchor = newAnchor;
+ configureBorder();
+ updateWidth();
+
+ if (myShowContent) {
+ setContentComponent(this);
+ }
+
+ minimizeParent.putClientProperty(IGNORE_WIDTH_KEY, null);
+ }
+
+ private void updateContent(boolean show, boolean flag) {
+ myShowContent = show;
+
+ String key = getMinKey();
+
+ JComponent minimizeParent = myContentSplitter.getInnerComponent();
+
+ if (show) {
+ minimizeParent.putClientProperty(key, null);
+ minimizeParent.remove(myMinimizeComponent);
+ }
+
+ setContentComponent(show ? this : null);
+
+ if (!show) {
+ minimizeParent.putClientProperty(key, myMinimizeComponent);
+ minimizeParent.add(myMinimizeComponent);
+ }
+
+ minimizeParent.revalidate();
+
+ if (flag) {
+ myPropertiesComponent.setValue(myShowStateKey, Boolean.toString(show));
+ }
+ }
+
+ private void setContentComponent(JComponent component) {
+ if (isLeft()) {
+ myContentSplitter.setFirstComponent(component);
+ }
+ else {
+ myContentSplitter.setLastComponent(component);
+ }
+ }
+
+ public void dispose() {
+ JComponent minimizeParent = myContentSplitter.getInnerComponent();
+ minimizeParent.removeComponentListener(myWidthListener);
+
+ setContentComponent(null);
+ myContent.dispose();
+
+ if (!myShowContent) {
+ minimizeParent.putClientProperty(getMinKey(), null);
+ minimizeParent.remove(myMinimizeComponent);
+ minimizeParent.revalidate();
+ }
+ }
+
+ private String getMinKey() {
+ return isLeft() ? LEFT_MIN_KEY : RIGHT_MIN_KEY;
+ }
+
+ public Object getContent() {
+ return myContent;
+ }
+
+ private boolean isLeft() {
+ return myAnchor == ToolWindowAnchor.LEFT;
+ }
+
+ private boolean isActive() {
+ IdeFocusManager fm = IdeFocusManager.getInstance(myProject);
+ Component component = fm.getFocusedDescendantFor(this);
+ if (component != null) {
+ return true;
+ }
+ Component owner = fm.getLastFocusedFor(WindowManager.getInstance().getIdeFrame(myProject));
+ return owner != null && SwingUtilities.isDescendingFrom(owner, this);
+ }
+
+ private void addAction(JPanel actionPanel, AnAction action) {
+ actionPanel.add(new ActionButton(action));
+ }
+
+ private DefaultActionGroup createGearPopupGroup() {
+ DefaultActionGroup group = new DefaultActionGroup();
+
+ group.add(myManager.createGearActions());
+ group.addSeparator();
+
+ ToolWindowType type = myManager.getToolWindow().getType();
+ if (type == ToolWindowType.DOCKED) {
+ group.add(myToggleAutoHideModeAction);
+ group.add(myToggleDockModeAction);
+ group.add(myToggleFloatingModeAction);
+ group.add(myToggleSideModeAction);
+ }
+ else if (type == ToolWindowType.FLOATING) {
+ group.add(myToggleAutoHideModeAction);
+ group.add(myToggleFloatingModeAction);
+ }
+ else if (type == ToolWindowType.SLIDING) {
+ group.add(myToggleDockModeAction);
+ group.add(myToggleFloatingModeAction);
+ }
+
+ return group;
+ }
+
+ private void showGearPopup(Component component, int x, int y) {
+ ActionPopupMenu popupMenu =
+ ((ActionManagerImpl)ActionManager.getInstance())
+ .createActionPopupMenu(ToolWindowContentUi.POPUP_PLACE, createGearPopupGroup(), new MenuItemPresentationFactory(true));
+ popupMenu.getComponent().show(component, x, y);
+ }
+
+ private class GearAction extends AnAction {
+ public GearAction() {
+ Presentation presentation = getTemplatePresentation();
+ presentation.setIcon(AllIcons.General.Gear);
+ presentation.setHoveredIcon(AllIcons.General.GearHover);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ int x = 0;
+ int y = 0;
+ InputEvent inputEvent = e.getInputEvent();
+ if (inputEvent instanceof MouseEvent) {
+ x = ((MouseEvent)inputEvent).getX();
+ y = ((MouseEvent)inputEvent).getY();
+ }
+
+ showGearPopup(inputEvent.getComponent(), x, y);
+ }
+ }
+
+ private class HideAction extends AnAction {
+ public HideAction() {
+ Presentation presentation = getTemplatePresentation();
+ presentation.setText(UIBundle.message("tool.window.hide.action.name"));
+ if (isLeft()) {
+ presentation.setIcon(AllIcons.General.HideLeftPart);
+ presentation.setHoveredIcon(AllIcons.General.HideLeftPartHover);
+ }
+ else {
+ presentation.setIcon(AllIcons.General.HideRightPart);
+ presentation.setHoveredIcon(AllIcons.General.HideRightPartHover);
+ }
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ updateContent(false, true);
+ }
+ }
+
+ private class TogglePinnedModeAction extends ToggleAction {
+ public TogglePinnedModeAction() {
+ copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_PINNED_MODE_ACTION_ID));
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return !myManager.getToolWindow().isAutoHide();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ ToolWindow window = myManager.getToolWindow();
+ window.setAutoHide(!window.isAutoHide());
+ myManager.setEditorMode(null);
+ }
+ }
+
+ private class ToggleDockModeAction extends ToggleAction {
+ public ToggleDockModeAction() {
+ copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_DOCK_MODE_ACTION_ID));
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myManager.getToolWindow().getType() == ToolWindowType.DOCKED;
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ ToolWindow window = myManager.getToolWindow();
+ ToolWindowType type = window.getType();
+ if (type == ToolWindowType.DOCKED) {
+ window.setType(ToolWindowType.SLIDING, null);
+ }
+ else if (type == ToolWindowType.SLIDING) {
+ window.setType(ToolWindowType.DOCKED, null);
+ }
+ myManager.setEditorMode(null);
+ }
+ }
+
+ private class ToggleFloatingModeAction extends ToggleAction {
+ public ToggleFloatingModeAction() {
+ copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_FLOATING_MODE_ACTION_ID));
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myManager.getToolWindow().getType() == ToolWindowType.FLOATING;
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ ToolWindow window = myManager.getToolWindow();
+ ToolWindowType type = window.getType();
+ if (type == ToolWindowType.FLOATING) {
+ window.setType(((ToolWindowEx)window).getInternalType(), null);
+ }
+ else {
+ window.setType(ToolWindowType.FLOATING, null);
+ }
+ myManager.setEditorMode(null);
+ }
+ }
+
+ private class ToggleSideModeAction extends ToggleAction {
+ public ToggleSideModeAction() {
+ copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_SIDE_MODE_ACTION_ID));
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myManager.getToolWindow().isSplitMode();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ myManager.getToolWindow().setSplitMode(state, null);
+ myManager.setEditorMode(null);
+ }
+ }
+
+ private class ActionButton extends Wrapper implements ActionListener {
+ private final AnAction myAction;
+
+ public ActionButton(AnAction action) {
+ myAction = action;
+
+ Presentation presentation = action.getTemplatePresentation();
+ InplaceButton button = new InplaceButton(KeymapUtil.createTooltipText(presentation.getText(), action), EmptyIcon.ICON_16, this) {
+ @Override
+ public boolean isActive() {
+ return LightToolWindow.this.isActive();
+ }
+ };
+ button.setHoveringEnabled(!SystemInfo.isMac);
+ setContent(button);
+
+ Icon icon = presentation.getIcon();
+ Icon hoveredIcon = presentation.getHoveredIcon();
+ button.setIcons(icon, icon, hoveredIcon == null ? icon : hoveredIcon);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ InputEvent inputEvent = e.getSource() instanceof InputEvent ? (InputEvent)e.getSource() : null;
+ myAction.actionPerformed(AnActionEvent.createFromInputEvent(myAction, inputEvent, ActionPlaces.UNKNOWN));
+ }
+ }
+
+ private class HeaderPanel extends JPanel {
+ private BufferedImage myActiveImage;
+ private BufferedImage myImage;
+
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension size = super.getPreferredSize();
+ return new Dimension(size.width, TabsUtil.getTabsHeight());
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ Dimension size = super.getMinimumSize();
+ return new Dimension(size.width, TabsUtil.getTabsHeight());
+ }
+
+ protected void _paintComponent(Graphics g) { // XXX: visual artifacts on linux
+ Rectangle r = getBounds();
+
+ Image image;
+ if (isActive()) {
+ if (myActiveImage == null || myActiveImage.getHeight() != r.height) {
+ myActiveImage = drawToBuffer(true, r.height);
+ }
+ image = myActiveImage;
+ }
+ else {
+ if (myImage == null || myImage.getHeight() != r.height) {
+ myImage = drawToBuffer(false, r.height);
+ }
+ image = myImage;
+ }
+
+ Graphics2D g2d = (Graphics2D)g;
+ Rectangle clipBounds = g2d.getClip().getBounds();
+ for (int x = clipBounds.x; x < clipBounds.x + clipBounds.width; x += 150) {
+ g2d.drawImage(image, x, 0, null);
+ }
+ }
+
+ protected boolean isActive() {
+ return LightToolWindow.this.isActive();
+ }
+ }
+
+ private static BufferedImage drawToBuffer(boolean active, int height) {
+ final int width = 150;
+
+ BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = image.createGraphics();
+ UIUtil.drawHeader(g, 0, width, height, active, true, false, false);
+ g.dispose();
+
+ return image;
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindowContent.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindowContent.java
new file mode 100644
index 000000000000..c3e00f7236f5
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindowContent.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface LightToolWindowContent {
+ void dispose();
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java
new file mode 100644
index 000000000000..0bfb083dec94
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.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.designer;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
+import com.intellij.openapi.fileEditor.FileEditorManagerListener;
+import com.intellij.openapi.project.DumbAwareRunnable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.startup.StartupManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ex.ToolWindowEx;
+import com.intellij.util.ParameterizedRunnable;
+import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.ui.update.MergingUpdateQueue;
+import com.intellij.util.ui.update.Update;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Alexander Lobas
+ */
+public abstract class LightToolWindowManager implements ProjectComponent {
+ public static final String EDITOR_MODE = "UI_DESIGNER_EDITOR_MODE.";
+
+ private final MergingUpdateQueue myWindowQueue = new MergingUpdateQueue(getComponentName(), 200, true, null);
+ protected final Project myProject;
+ protected final FileEditorManager myFileEditorManager;
+ protected volatile ToolWindow myToolWindow;
+ private volatile boolean myToolWindowDisposed;
+
+ private final PropertiesComponent myPropertiesComponent;
+ public final String myEditorModeKey;
+ private ToggleEditorModeAction myLeftEditorModeAction;
+ private ToggleEditorModeAction myRightEditorModeAction;
+
+ private MessageBusConnection myConnection;
+ private final FileEditorManagerListener myListener = new FileEditorManagerListener() {
+ @Override
+ public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ bindToDesigner(getActiveDesigner());
+ }
+
+ @Override
+ public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ bindToDesigner(getActiveDesigner());
+ }
+ });
+ }
+
+ @Override
+ public void selectionChanged(@NotNull FileEditorManagerEvent event) {
+ bindToDesigner(getDesigner(event.getNewEditor()));
+ }
+ };
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // ToolWindow
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ protected LightToolWindowManager(Project project, FileEditorManager fileEditorManager) {
+ myProject = project;
+ myFileEditorManager = fileEditorManager;
+ myPropertiesComponent = PropertiesComponent.getInstance(myProject);
+ myEditorModeKey = EDITOR_MODE + getComponentName() + ".STATE";
+ }
+
+ @Override
+ public void projectOpened() {
+ initToolWindow();
+
+ StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
+ public void run() {
+ if (getEditorMode() == null) {
+ initListeners();
+ bindToDesigner(getActiveDesigner());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void projectClosed() {
+ if (!myToolWindowDisposed) {
+ disposeComponent();
+ myToolWindowDisposed = true;
+ myToolWindow = null;
+ }
+ }
+
+ private void initListeners() {
+ myConnection = myProject.getMessageBus().connect(myProject);
+ myConnection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, myListener);
+ }
+
+ private void removeListeners() {
+ myConnection.disconnect();
+ myConnection = null;
+ }
+
+ @Nullable
+ protected abstract DesignerEditorPanelFacade getDesigner(FileEditor editor);
+
+ @Nullable
+ public DesignerEditorPanelFacade getActiveDesigner() {
+ for (FileEditor editor : myFileEditorManager.getSelectedEditors()) {
+ DesignerEditorPanelFacade designer = getDesigner(editor);
+ if (designer != null) {
+ return designer;
+ }
+ }
+
+ return null;
+ }
+
+ private void bindToDesigner(final DesignerEditorPanelFacade designer) {
+ myWindowQueue.cancelAllUpdates();
+ myWindowQueue.queue(new Update("update") {
+ @Override
+ public void run() {
+ if (myToolWindowDisposed) {
+ return;
+ }
+ if (myToolWindow == null) {
+ if (designer == null) {
+ return;
+ }
+ initToolWindow();
+ }
+ updateToolWindow(designer);
+ }
+ });
+ }
+
+ protected abstract void initToolWindow();
+
+ protected abstract void updateToolWindow(@Nullable DesignerEditorPanelFacade designer);
+
+ protected final void initGearActions() {
+ ToolWindowEx toolWindow = (ToolWindowEx)myToolWindow;
+ toolWindow.setAdditionalGearActions(new DefaultActionGroup(createGearActions()));
+ }
+
+ protected abstract ToolWindowAnchor getAnchor();
+
+ @Override
+ public void initComponent() {
+ }
+
+ @Override
+ public void disposeComponent() {
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // LightToolWindow
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ public final ActionGroup createGearActions() {
+ DefaultActionGroup group = new DefaultActionGroup("In Editor Mode", true);
+
+ if (myLeftEditorModeAction == null) {
+ myLeftEditorModeAction = createToggleAction(ToolWindowAnchor.LEFT);
+ }
+ group.add(myLeftEditorModeAction);
+
+ if (myRightEditorModeAction == null) {
+ myRightEditorModeAction = createToggleAction(ToolWindowAnchor.RIGHT);
+ }
+ group.add(myRightEditorModeAction);
+
+ return group;
+ }
+
+ protected abstract ToggleEditorModeAction createToggleAction(ToolWindowAnchor anchor);
+
+ public final void bind(@NotNull DesignerEditorPanelFacade designer) {
+ if (isEditorMode()) {
+ myCreateAction.run(designer);
+ }
+ }
+
+ public final void dispose(@NotNull DesignerEditorPanelFacade designer) {
+ if (isEditorMode()) {
+ disposeContent(designer);
+ }
+ }
+
+ protected final Object getContent(@NotNull DesignerEditorPanelFacade designer) {
+ LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(getComponentName());
+ return toolWindow.getContent();
+ }
+
+ protected abstract LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer);
+
+ protected final LightToolWindow createContent(@NotNull DesignerEditorPanelFacade designer,
+ @NotNull LightToolWindowContent content,
+ @NotNull String title,
+ @NotNull Icon icon,
+ @NotNull JComponent component,
+ @NotNull JComponent focusedComponent,
+ int defaultWidth,
+ @Nullable AnAction[] actions) {
+ return new LightToolWindow(content,
+ title,
+ icon,
+ component,
+ focusedComponent,
+ designer.getContentSplitter(),
+ getEditorMode(),
+ this,
+ myProject,
+ myPropertiesComponent,
+ getComponentName(),
+ defaultWidth,
+ actions);
+ }
+
+ protected final void disposeContent(DesignerEditorPanelFacade designer) {
+ String key = getComponentName();
+ LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(key);
+ designer.putClientProperty(key, null);
+ toolWindow.dispose();
+ }
+
+ private final ParameterizedRunnable<DesignerEditorPanelFacade> myCreateAction = new ParameterizedRunnable<DesignerEditorPanelFacade>() {
+ @Override
+ public void run(DesignerEditorPanelFacade designer) {
+ designer.putClientProperty(getComponentName(), createContent(designer));
+ }
+ };
+
+ private final ParameterizedRunnable<DesignerEditorPanelFacade> myUpdateAnchorAction =
+ new ParameterizedRunnable<DesignerEditorPanelFacade>() {
+ @Override
+ public void run(DesignerEditorPanelFacade designer) {
+ LightToolWindow toolWindow = (LightToolWindow)designer.getClientProperty(getComponentName());
+ toolWindow.updateAnchor(getEditorMode());
+ }
+ };
+
+ private final ParameterizedRunnable<DesignerEditorPanelFacade> myDisposeAction = new ParameterizedRunnable<DesignerEditorPanelFacade>() {
+ @Override
+ public void run(DesignerEditorPanelFacade designer) {
+ disposeContent(designer);
+ }
+ };
+
+ private void runUpdateContent(ParameterizedRunnable<DesignerEditorPanelFacade> action) {
+ for (FileEditor editor : myFileEditorManager.getAllEditors()) {
+ DesignerEditorPanelFacade designer = getDesigner(editor);
+ if (designer != null) {
+ action.run(designer);
+ }
+ }
+ }
+
+ protected final boolean isEditorMode() {
+ return getEditorMode() != null;
+ }
+
+ @Nullable
+ final ToolWindowAnchor getEditorMode() {
+ String value = myPropertiesComponent.getValue(myEditorModeKey);
+ if (value == null) {
+ return getAnchor();
+ }
+ return value.equals("ToolWindow") ? null : ToolWindowAnchor.fromText(value);
+ }
+
+ final void setEditorMode(@Nullable ToolWindowAnchor newState) {
+ ToolWindowAnchor oldState = getEditorMode();
+ myPropertiesComponent.setValue(myEditorModeKey, newState == null ? "ToolWindow" : newState.toString());
+
+ if (oldState != null && newState != null) {
+ runUpdateContent(myUpdateAnchorAction);
+ }
+ else if (newState != null) {
+ removeListeners();
+ updateToolWindow(null);
+ runUpdateContent(myCreateAction);
+ }
+ else {
+ runUpdateContent(myDisposeAction);
+ initListeners();
+ bindToDesigner(getActiveDesigner());
+ }
+ }
+
+ final ToolWindow getToolWindow() {
+ return myToolWindow;
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/designer/ToggleEditorModeAction.java b/platform/platform-impl/src/com/intellij/designer/ToggleEditorModeAction.java
new file mode 100644
index 000000000000..668a0405f4b2
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/designer/ToggleEditorModeAction.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.designer;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+
+/**
+ * @author Alexander Lobas
+ */
+public abstract class ToggleEditorModeAction extends ToggleAction {
+ protected final LightToolWindowManager myManager;
+ protected final Project myProject;
+ private final ToolWindowAnchor myAnchor;
+
+ public ToggleEditorModeAction(LightToolWindowManager manager, Project project, ToolWindowAnchor anchor) {
+ super(StringUtil.capitalize(anchor.toString()), "Pin/unpin tool window to " + anchor + " side UI Designer Editor", null);
+ myManager = manager;
+ myProject = project;
+ myAnchor = anchor;
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myAnchor == myManager.getEditorMode();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ if (state) {
+ myManager.setEditorMode(myAnchor);
+
+ LightToolWindowManager manager = getOppositeManager();
+ if (manager.getEditorMode() == myAnchor) {
+ manager.setEditorMode(myAnchor == ToolWindowAnchor.LEFT ? ToolWindowAnchor.RIGHT : ToolWindowAnchor.LEFT);
+ }
+ }
+ else {
+ myManager.setEditorMode(null);
+ }
+ }
+
+ protected abstract LightToolWindowManager getOppositeManager();
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java
index e430f9fdb513..b951b59ed9dd 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.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,11 +16,11 @@
package com.intellij.diagnostic;
import com.intellij.CommonBundle;
-import com.intellij.errorreport.ErrorReportSender;
import com.intellij.errorreport.bean.ErrorBean;
import com.intellij.errorreport.error.InternalEAPException;
import com.intellij.errorreport.error.NoSuchEAPUserException;
import com.intellij.errorreport.error.UpdateAvailableException;
+import com.intellij.errorreport.itn.ITNProxy;
import com.intellij.ide.DataManager;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
@@ -32,6 +32,7 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diagnostic.SubmittedReportInfo;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
@@ -39,7 +40,7 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.xml.util.XmlStringUtil;
-import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -49,60 +50,39 @@ import java.awt.*;
*/
public class ITNReporter extends ErrorReportSubmitter {
private static int previousExceptionThreadId = 0;
- private static boolean wasException = false;
- @NonNls private static final String URL_HEADER = "http://www.intellij.net/tracker/idea/viewSCR?publicId=";
+ @Override
public String getReportActionText() {
return DiagnosticBundle.message("error.report.to.jetbrains.action");
}
- public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) {
- // obsolete API
- return new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED);
- }
-
@Override
- public boolean trySubmitAsync(IdeaLoggingEvent[] events,
- String additionalInfo,
- Component parentComponent,
- Consumer<SubmittedReportInfo> consumer) {
- return sendError(events[0], additionalInfo, parentComponent, consumer);
+ public boolean submit(@NotNull IdeaLoggingEvent[] events,
+ String additionalInfo,
+ @NotNull Component parentComponent,
+ @NotNull Consumer<SubmittedReportInfo> consumer) {
+ ErrorBean errorBean = new ErrorBean(events[0].getThrowable(), IdeaLogger.ourLastActionId);
+ return doSubmit(events[0], parentComponent, consumer, errorBean, additionalInfo);
}
/**
- * Could be used to enable error reporting even in release versions from non-internal mode.
- * @return false by default.
+ * Used to enable error reporting even in release versions.
*/
- @SuppressWarnings({"MethodMayBeStatic", "UnusedParameters"})
public boolean showErrorInRelease(IdeaLoggingEvent event) {
return false;
}
- /**
- * @noinspection ThrowablePrintStackTrace
- */
- private static boolean sendError(IdeaLoggingEvent event,
- String additionalInfo,
- final Component parentComponent,
- final Consumer<SubmittedReportInfo> callback) {
- ErrorBean errorBean = new ErrorBean(event.getThrowable(), IdeaLogger.ourLastActionId);
-
- return doSubmit(event, parentComponent, callback, errorBean, additionalInfo);
- }
-
private static boolean doSubmit(final IdeaLoggingEvent event,
- final Component parentComponent,
- final Consumer<SubmittedReportInfo> callback,
- final ErrorBean errorBean,
- final String description) {
+ final Component parentComponent,
+ final Consumer<SubmittedReportInfo> callback,
+ final ErrorBean errorBean,
+ final String description) {
final DataContext dataContext = DataManager.getInstance().getDataContext(parentComponent);
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
- final ErrorReportConfigurable errorReportConfigurable = ErrorReportConfigurable.getInstance();
- if (!errorReportConfigurable.KEEP_ITN_PASSWORD &&
- !StringUtil.isEmpty(errorReportConfigurable.ITN_LOGIN) &&
- StringUtil.isEmpty(errorReportConfigurable.getPlainItnPassword())) {
- final JetBrainsAccountDialog dlg = new JetBrainsAccountDialog(parentComponent);
+ ErrorReportConfigurable settings = ErrorReportConfigurable.getInstance();
+ if (!settings.KEEP_ITN_PASSWORD && !StringUtil.isEmpty(settings.ITN_LOGIN) && StringUtil.isEmpty(settings.getPlainItnPassword())) {
+ JetBrainsAccountDialog dlg = new JetBrainsAccountDialog(parentComponent);
dlg.show();
if (!dlg.isOK()) {
return false;
@@ -129,55 +109,46 @@ public class ITNReporter extends ErrorReportSubmitter {
}
Object data = event.getData();
-
if (data instanceof AbstractMessage) {
errorBean.setAssigneeId(((AbstractMessage)data).getAssigneeId());
}
-
if (data instanceof LogMessageEx) {
errorBean.setAttachments(((LogMessageEx)data).getAttachments());
}
- @NonNls String login = errorReportConfigurable.ITN_LOGIN;
- @NonNls String password = errorReportConfigurable.getPlainItnPassword();
- if (login.trim().length() == 0 && password.trim().length() == 0) {
+ String login = settings.ITN_LOGIN;
+ String password = settings.getPlainItnPassword();
+ if (StringUtil.isEmptyOrSpaces(login) && StringUtil.isEmptyOrSpaces(password)) {
login = "idea_anonymous";
password = "guest";
}
- ErrorReportSender.sendError(project, login, password, errorBean, new Consumer<Integer>() {
- @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
+ ITNProxy.sendError(project, login, password, errorBean, new Consumer<Integer>() {
@Override
public void consume(Integer threadId) {
- previousExceptionThreadId = threadId;
- wasException = true;
- final SubmittedReportInfo reportInfo = new SubmittedReportInfo(URL_HEADER + threadId, String.valueOf(threadId),
- SubmittedReportInfo.SubmissionStatus.NEW_ISSUE);
+ updatePreviousThreadId(threadId);
+ String url = ITNProxy.getBrowseUrl(threadId);
+ String linkText = String.valueOf(threadId);
+ final SubmittedReportInfo reportInfo = new SubmittedReportInfo(url, linkText, SubmittedReportInfo.SubmissionStatus.NEW_ISSUE);
callback.consume(reportInfo);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
StringBuilder text = new StringBuilder();
- final String url = IdeErrorsDialog.getUrl(reportInfo, true);
- IdeErrorsDialog.appendSubmissionInformation(reportInfo, text, url);
- text.append(".");
- if (reportInfo.getStatus() != SubmittedReportInfo.SubmissionStatus.FAILED) {
- text.append("<br/>").append(DiagnosticBundle.message("error.report.gratitude"));
- }
-
- NotificationType type = reportInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED
- ? NotificationType.ERROR
- : NotificationType.INFORMATION;
- NotificationListener listener = url != null ? new NotificationListener.UrlOpeningListener(true) : null;
- ReportMessages.GROUP.createNotification(ReportMessages.ERROR_REPORT,
- XmlStringUtil.wrapInHtml(text),
- type, listener).setImportant(false).notify(project);
+ IdeErrorsDialog.appendSubmissionInformation(reportInfo, text);
+ text.append('.').append("<br/>").append(DiagnosticBundle.message("error.report.gratitude"));
+ String content = XmlStringUtil.wrapInHtml(text);
+ ReportMessages.GROUP
+ .createNotification(ReportMessages.ERROR_REPORT, content, NotificationType.INFORMATION, NotificationListener.URL_OPENING_LISTENER)
+ .setImportant(false)
+ .notify(project);
}
});
}
}, new Consumer<Exception>() {
@Override
public void consume(final Exception e) {
+ Logger.getInstance(ITNReporter.class).info("reporting failed: " + e);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
@@ -192,13 +163,12 @@ public class ITNReporter extends ErrorReportSubmitter {
msg = DiagnosticBundle.message("error.report.sending.failure");
}
if (e instanceof UpdateAvailableException) {
- String message = DiagnosticBundle.message(
- "error.report.new.eap.build.message", e.getMessage());
- showMessageDialog(parentComponent, project, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon());
- callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
+ String message = DiagnosticBundle.message("error.report.new.eap.build.message", e.getMessage());
+ showMessageDialog(parentComponent, project, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon());
+ callback.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED));
}
else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != Messages.YES) {
- callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
+ callback.consume(new SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED));
}
else {
if (e instanceof NoSuchEAPUserException) {
@@ -225,10 +195,15 @@ public class ITNReporter extends ErrorReportSubmitter {
return true;
}
+ private static void updatePreviousThreadId(Integer threadId) {
+ previousExceptionThreadId = threadId;
+ }
+
private static void showMessageDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
Messages.showMessageDialog(parentComponent, message, title, icon);
- } else {
+ }
+ else {
Messages.showMessageDialog(project, message, title, icon);
}
}
@@ -237,7 +212,8 @@ public class ITNReporter extends ErrorReportSubmitter {
private static int showYesNoDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
return Messages.showYesNoDialog(parentComponent, message, title, icon);
- } else {
+ }
+ else {
return Messages.showYesNoDialog(project, message, title, icon);
}
}
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index ac296d677232..a0e96c5d674e 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.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.
@@ -563,9 +563,9 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
String url = null;
if (message.isSubmitted()) {
- final SubmittedReportInfo info = message.getSubmissionInfo();
- url = getUrl(info, getSubmitter(throwable) instanceof ITNReporter);
- appendSubmissionInformation(info, text, url);
+ SubmittedReportInfo info = message.getSubmissionInfo();
+ url = info.getURL();
+ appendSubmissionInformation(info, text);
text.append(". ");
}
else if (message.isSubmitting()) {
@@ -578,33 +578,18 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
myInfoLabel.setHyperlinkTarget(url);
}
- public static void appendSubmissionInformation(SubmittedReportInfo info, StringBuilder out, @Nullable String url) {
+ public static void appendSubmissionInformation(SubmittedReportInfo info, StringBuilder out) {
if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED) {
out.append(" ").append(DiagnosticBundle.message("error.list.message.submission.failed"));
}
- else {
- if (info.getLinkText() != null) {
- out.append(" ").append(DiagnosticBundle.message("error.list.message.submitted.as.link", url, info.getLinkText()));
- if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE) {
- out.append(" ").append(DiagnosticBundle.message("error.list.message.duplicate"));
- }
- }
- else {
- out.append(DiagnosticBundle.message("error.list.message.submitted"));
+ else if (info.getURL() != null && info.getLinkText() != null) {
+ out.append(" ").append(DiagnosticBundle.message("error.list.message.submitted.as.link", info.getURL(), info.getLinkText()));
+ if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE) {
+ out.append(" ").append(DiagnosticBundle.message("error.list.message.duplicate"));
}
}
- }
-
- @Nullable
- public static String getUrl(SubmittedReportInfo info, boolean reportedToJetbrains) {
- if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED || info.getLinkText() == null) {
- return null;
- }
- if (reportedToJetbrains) {
- return "http://ea.jetbrains.com/browser/ea_reports/" + info.getLinkText();
- }
else {
- return info.getURL();
+ out.append(DiagnosticBundle.message("error.list.message.submitted"));
}
}
@@ -919,38 +904,37 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
private boolean reportMessage(final AbstractMessage logMessage, final boolean dialogClosed) {
final ErrorReportSubmitter submitter = getSubmitter(logMessage.getThrowable());
+ if (submitter == null) return false;
- if (submitter != null) {
- logMessage.setSubmitting(true);
- if (!dialogClosed) {
- updateControls();
- }
- Container parentComponent;
- if (dialogClosed) {
- IdeFrame ideFrame = UIUtil.getParentOfType(IdeFrame.class, getContentPane());
- parentComponent = ideFrame.getComponent();
- }
- else {
- parentComponent = getContentPane();
- }
- return submitter.trySubmitAsync(getEvents(logMessage), logMessage.getAdditionalInfo(), parentComponent,
- new Consumer<SubmittedReportInfo>() {
- @Override
- public void consume(final SubmittedReportInfo submittedReportInfo) {
- logMessage.setSubmitting(false);
- logMessage.setSubmitted(submittedReportInfo);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- if (!dialogClosed) {
- updateOnSubmit();
- }
- }
- });
- }
- });
+ logMessage.setSubmitting(true);
+ if (!dialogClosed) {
+ updateControls();
}
- return false;
+ Container parentComponent;
+ if (dialogClosed) {
+ IdeFrame ideFrame = UIUtil.getParentOfType(IdeFrame.class, getContentPane());
+ parentComponent = ideFrame.getComponent();
+ }
+ else {
+ parentComponent = getContentPane();
+ }
+
+ return submitter.submit(
+ getEvents(logMessage), logMessage.getAdditionalInfo(), parentComponent, new Consumer<SubmittedReportInfo>() {
+ @Override
+ public void consume(final SubmittedReportInfo submittedReportInfo) {
+ logMessage.setSubmitting(false);
+ logMessage.setSubmitted(submittedReportInfo);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!dialogClosed) {
+ updateOnSubmit();
+ }
+ }
+ });
+ }
+ });
}
private IdeaLoggingEvent[] getEvents(final AbstractMessage logMessage) {
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java b/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java
deleted file mode 100644
index 88798381f8a8..000000000000
--- a/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.diagnostic;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.application.ApplicationInfo;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.SystemProperties;
-import com.intellij.util.io.ZipUtil;
-import org.apache.commons.net.ftp.FTPClient;
-import org.apache.commons.net.ftp.FTPReply;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.*;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.zip.ZipOutputStream;
-
-/**
- * @author yole
- */
-public class SubmitPerformanceReportAction extends AnAction implements DumbAware {
- private final DateFormat myDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss");
-
- private static final String MESSAGE_TITLE = "Submit Performance Report";
-
- public void actionPerformed(final AnActionEvent e) {
- String reportFileName = "perf_" + ApplicationInfo.getInstance().getBuild().asString() + "_" +
- SystemProperties.getUserName() + "_" + myDateFormat.format(new Date()) + ".zip";
- final File reportPath = new File(SystemProperties.getUserHome(), reportFileName);
- final File logDir = new File(PathManager.getLogPath());
- final Project project = e.getData(CommonDataKeys.PROJECT);
-
- final boolean[] archiveCreated = new boolean[1];
- final boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
- public void run() {
- try {
- ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(reportPath));
- ZipUtil.addDirToZipRecursively(zip, reportPath, logDir, "", new FileFilter() {
- public boolean accept(final File pathname) {
- ProgressManager.checkCanceled();
-
- if (logDir.equals(pathname.getParentFile())) {
- return pathname.getPath().contains("threadDumps");
- }
- return true;
- }
- }, null);
- zip.close();
- archiveCreated[0] = true;
- }
- catch (final IOException ex) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- Messages.showErrorDialog(project, "Failed to create performance report archive: " + ex.getMessage(), MESSAGE_TITLE);
- }
- });
- }
- }
- }, "Collecting Performance Report data", true, project);
-
- if (!completed ||
- !archiveCreated[0]) {
- return;
- }
-
- int rc = Messages.showYesNoDialog(project, "The performance report has been saved to\n" + reportPath +
- "\n\nWould you like to submit it to JetBrains?", MESSAGE_TITLE,
- Messages.getQuestionIcon());
- if (rc == Messages.YES) {
- ProgressManager.getInstance().run(new Task.Backgroundable(project, "Uploading Performance Report") {
- public void run(@NotNull final ProgressIndicator indicator) {
- final String error = uploadFileToFTP(reportPath, "ftp.intellij.net", ".uploads", indicator);
- if (error != null) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- Messages.showErrorDialog(error, MESSAGE_TITLE);
- }
- });
- }
- }
- });
- }
- }
-
- @Nullable
- private static String uploadFileToFTP(final File reportPath, @NonNls final String ftpSite, @NonNls final String directory,
- final ProgressIndicator indicator) {
- FTPClient ftp = new FTPClient();
- ftp.setConnectTimeout(30 * 1000);
- try {
- indicator.setText("Connecting to server...");
- ftp.connect(ftpSite);
- indicator.setText("Connected to server");
-
- if (!ftp.login("anonymous", "anonymous@jetbrains.com")) {
- return "Failed to login";
- }
- indicator.setText("Logged in");
-
- // After connection attempt, you should check the reply code to verify
- // success.
- int reply = ftp.getReplyCode();
-
- if (!FTPReply.isPositiveCompletion(reply)) {
- ftp.disconnect();
- return "FTP server refused connection: " + reply;
- }
- if (!ftp.changeWorkingDirectory(directory)) {
- return "Failed to change directory";
- }
-
- // else won't work behind FW
- ftp.enterLocalPassiveMode();
-
- if (!ftp.setFileType(FTPClient.BINARY_FILE_TYPE)) {
- return "Failed to switch to binary mode";
- }
-
- indicator.setText("Transferring (" + StringUtil.formatFileSize(reportPath.length()) + ")");
- FileInputStream readStream = new FileInputStream(reportPath);
- try {
- if (!ftp.storeFile(reportPath.getName(), readStream)) {
- return "Failed to upload file";
- }
- } catch (IOException e) {
- return "Error during transfer: " + e.getMessage();
- }
- finally {
- readStream.close();
- }
- ftp.logout();
- return null;
- }
- catch (IOException e) {
- return "Failed to upload: " + e.getMessage();
- }
- finally {
- if (ftp.isConnected()) {
- try {
- ftp.disconnect();
- }
- catch (IOException ioe) {
- // do nothing
- }
- }
- }
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java b/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java
deleted file mode 100644
index 7cce2895fd85..000000000000
--- a/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.errorreport;
-
-import com.intellij.diagnostic.DiagnosticBundle;
-import com.intellij.errorreport.bean.ErrorBean;
-import com.intellij.errorreport.itn.ITNProxy;
-import com.intellij.idea.IdeaLogger;
-import com.intellij.openapi.progress.EmptyProgressIndicator;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Consumer;
-import com.intellij.util.net.HttpConfigurable;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Created by IntelliJ IDEA.
- * User: stathik
- * Date: May 22, 2003
- * Time: 8:57:19 PM
- * To change this template use Options | File Templates.
- */
-public class ErrorReportSender {
- @NonNls public static final String PREPARE_URL = "http://www.intellij.net/";
-
- private ErrorReportSender() {
- }
-
- static class SendTask {
- private final Project myProject;
- private String myLogin;
- private String myPassword;
- private ErrorBean errorBean;
-
- public SendTask(final Project project, ErrorBean errorBean) {
- myProject = project;
- this.errorBean = errorBean;
- }
-
- public void setCredentials(String login, String password) {
- myLogin = login;
- myPassword = password;
- }
-
- public void sendReport(final Consumer<Integer> callback, final Consumer<Exception> errback) {
- Task.Backgroundable task = new Task.Backgroundable(myProject, DiagnosticBundle.message("title.submitting.error.report")) {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- try {
- HttpConfigurable.getInstance().prepareURL(PREPARE_URL);
-
- if (!StringUtil.isEmpty(myLogin)) {
- int threadId = ITNProxy.postNewThread(
- myLogin,
- myPassword,
- errorBean,
- IdeaLogger.getOurCompilationTimestamp());
- callback.consume(threadId);
- }
- }
- catch (Exception ex) {
- errback.consume(ex);
- }
- }
- };
- if (myProject == null) {
- task.run(new EmptyProgressIndicator());
- }
- else {
- ProgressManager.getInstance().run(task);
- }
- }
- }
-
- public static void sendError(Project project, String login, String password, ErrorBean error,
- Consumer<Integer> callback, Consumer<Exception> errback) {
- SendTask sendTask = new SendTask(project, error);
- sendTask.setCredentials(login, password);
- sendTask.sendReport(callback, errback);
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.java b/platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.java
index 89832a8b7864..d4c17f7a89d7 100644
--- a/platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.java
+++ b/platform/platform-impl/src/com/intellij/errorreport/bean/ErrorBean.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.
@@ -16,10 +16,9 @@
package com.intellij.errorreport.bean;
import com.intellij.openapi.diagnostic.Attachment;
+import com.intellij.util.ExceptionUtil;
import org.jetbrains.annotations.NonNls;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
import java.util.Collections;
import java.util.List;
@@ -41,11 +40,7 @@ public class ErrorBean {
public ErrorBean(Throwable throwable, String lastAction) {
if (throwable != null) {
message = throwable.getMessage();
-
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- //noinspection IOResourceOpenedButNotSafelyClosed
- throwable.printStackTrace(new PrintStream(stream, true));
- stackTrace = stream.toString();
+ stackTrace = ExceptionUtil.getThrowableText(throwable);
}
this.lastAction = lastAction;
}
diff --git a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
index ec112437520b..4339b36cbf22 100644
--- a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
+++ b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
@@ -20,202 +20,292 @@ import com.intellij.errorreport.bean.ErrorBean;
import com.intellij.errorreport.error.InternalEAPException;
import com.intellij.errorreport.error.NoSuchEAPUserException;
import com.intellij.errorreport.error.UpdateAvailableException;
+import com.intellij.idea.IdeaLogger;
import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.diagnostic.Attachment;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
-import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Consumer;
import com.intellij.util.SystemProperties;
-import com.intellij.util.net.HttpConfigurable;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.net.ssl.CertificateUtil;
+import org.jetbrains.annotations.NotNull;
+import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
-import java.util.ArrayList;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
- * Created by IntelliJ IDEA.
- * User: stathik
- * Date: Aug 4, 2003
- * Time: 8:12:00 PM
- * To change this template use Options | File Templates.
+ * @author stathik
+ * @since Aug 4, 2003
*/
public class ITNProxy {
- @NonNls public static final String ENCODING = "UTF8";
- public static final String POST_DELIMITER = "&";
+ private static final String NEW_THREAD_VIEW_URL = "https://ea.jetbrains.com/browser/ea_reports/";
+ private static final String NEW_THREAD_POST_URL = "https://ea-report.jetbrains.com/trackerRpc/idea/createScr";
+ private static final String ENCODING = "UTF8";
+
+ public static void sendError(Project project,
+ final String login,
+ final String password,
+ final ErrorBean error,
+ final Consumer<Integer> callback,
+ final Consumer<Exception> errback) {
+ if (StringUtil.isEmpty(login)) {
+ return;
+ }
- @NonNls public static final String NEW_THREAD_URL = "http://www.intellij.net/trackerRpc/idea/createScr";
+ Task.Backgroundable task = new Task.Backgroundable(project, DiagnosticBundle.message("title.submitting.error.report")) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ try {
+ int threadId = postNewThread(login, password, error);
+ callback.consume(threadId);
+ }
+ catch (Exception ex) {
+ errback.consume(ex);
+ }
+ }
+ };
+
+ if (project == null) {
+ task.run(new EmptyProgressIndicator());
+ }
+ else {
+ ProgressManager.getInstance().run(task);
+ }
+ }
- @NonNls private static final String HTTP_CONTENT_LENGTH = "Content-Length";
- @NonNls private static final String HTTP_CONTENT_TYPE = "Content-Type";
- @NonNls private static final String HTTP_WWW_FORM = "application/x-www-form-urlencoded";
- @NonNls private static final String HTTP_POST = "POST";
+ public static String getBrowseUrl(int threadId) {
+ return NEW_THREAD_VIEW_URL + threadId;
+ }
- public static int postNewThread (String login, String password, ErrorBean error, String compilationTimestamp)
- throws IOException, NoSuchEAPUserException, InternalEAPException, UpdateAvailableException {
+ private static SSLContext ourSslContext;
- @NonNls List<Couple<String>> params = createParametersFor(login,
- password,
- error,
- compilationTimestamp,
- ApplicationManager.getApplication(),
- (ApplicationInfoEx) ApplicationInfo.getInstance(),
- ApplicationNamesInfo.getInstance(),
- UpdateSettings.getInstance());
+ private static int postNewThread(String login, String password, ErrorBean error) throws Exception {
+ if (ourSslContext == null) {
+ ourSslContext = initContext();
+ }
- HttpURLConnection connection = post(new URL(NEW_THREAD_URL), join(params));
+ Map<String, String> params = createParameters(login, password, error);
+ HttpURLConnection connection = post(new URL(NEW_THREAD_POST_URL), join(params));
int responseCode = connection.getResponseCode();
-
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new InternalEAPException(DiagnosticBundle.message("error.http.result.code", responseCode));
}
- String reply;
-
- InputStream is = new BufferedInputStream(connection.getInputStream());
+ String response;
+ InputStream is = connection.getInputStream();
try {
- reply = readFrom(is);
- } finally {
+ byte[] bytes = FileUtil.loadBytes(is);
+ response = new String(bytes, ENCODING);
+ }
+ finally {
is.close();
}
- if ("unauthorized".equals(reply)) {
+ if ("unauthorized".equals(response)) {
throw new NoSuchEAPUserException(login);
}
-
- if (reply.startsWith("update ")) {
- throw new UpdateAvailableException(reply.substring(7));
+ if (response.startsWith("update ")) {
+ throw new UpdateAvailableException(response.substring(7));
}
-
- if (reply.startsWith("message ")) {
- throw new InternalEAPException(reply.substring(8));
+ if (response.startsWith("message ")) {
+ throw new InternalEAPException(response.substring(8));
}
try {
- return Integer.valueOf(reply.trim()).intValue();
- } catch (NumberFormatException ex) {
- // Tibor!!!! :-E
+ return Integer.valueOf(response.trim()).intValue();
+ }
+ catch (NumberFormatException ex) {
throw new InternalEAPException(DiagnosticBundle.message("error.itn.returns.wrong.data"));
}
}
- private static List<Couple<String>> createParametersFor(String login,
- String password,
- ErrorBean error,
- String compilationTimestamp, Application application, ApplicationInfoEx appInfo,
- ApplicationNamesInfo namesInfo,
- UpdateSettings updateSettings) {
- @NonNls List<Couple<String>> params = new ArrayList<Couple<String>>();
-
- params.add(Couple.of("protocol.version", "1"));
+ private static Map<String, String> createParameters(String login, String password, ErrorBean error) {
+ Map<String, String> params = ContainerUtil.newLinkedHashMap(40);
- params.add(Couple.of("user.login", login));
- params.add(Couple.of("user.password", password));
+ params.put("protocol.version", "1");
- params.add(Couple.of("os.name", SystemProperties.getOsName()));
+ params.put("user.login", login);
+ params.put("user.password", password);
- params.add(Couple.of("java.version", SystemProperties.getJavaVersion()));
- params.add(Couple.of("java.vm.vendor", SystemProperties.getJavaVmVendor()));
+ params.put("os.name", SystemProperties.getOsName());
+ params.put("java.version", SystemProperties.getJavaVersion());
+ params.put("java.vm.vendor", SystemProperties.getJavaVmVendor());
- params.add(Couple.of("app.name", namesInfo.getProductName()));
- params.add(Couple.of("app.name.full", namesInfo.getFullProductName()));
- params.add(Couple.of("app.name.version", appInfo.getVersionName()));
- params.add(Couple.of("app.eap", Boolean.toString(appInfo.isEAP())));
- params.add(Couple.of("app.internal", Boolean.toString(application.isInternal())));
- params.add(Couple.of("app.build", appInfo.getBuild().asString()));
- params.add(Couple.of("app.version.major", appInfo.getMajorVersion()));
- params.add(Couple.of("app.version.minor", appInfo.getMinorVersion()));
- params.add(Couple.of("app.build.date", format(appInfo.getBuildDate())));
- params.add(Couple.of("app.build.date.release", format(appInfo.getMajorReleaseBuildDate())));
- params.add(Couple.of("app.compilation.timestamp", compilationTimestamp));
+ ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
+ ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance();
+ Application application = ApplicationManager.getApplication();
+ params.put("app.name", namesInfo.getProductName());
+ params.put("app.name.full", namesInfo.getFullProductName());
+ params.put("app.name.version", appInfo.getVersionName());
+ params.put("app.eap", Boolean.toString(appInfo.isEAP()));
+ params.put("app.internal", Boolean.toString(application.isInternal()));
+ params.put("app.build", appInfo.getBuild().asString());
+ params.put("app.version.major", appInfo.getMajorVersion());
+ params.put("app.version.minor", appInfo.getMinorVersion());
+ params.put("app.build.date", format(appInfo.getBuildDate()));
+ params.put("app.build.date.release", format(appInfo.getMajorReleaseBuildDate()));
+ params.put("app.compilation.timestamp", IdeaLogger.getOurCompilationTimestamp());
- params.add(Couple.of("update.channel.status", updateSettings.getSelectedChannelStatus().getCode()));
- params.add(Couple.of("update.ignored.builds", StringUtil.join(updateSettings.getIgnoredBuildNumbers(), ",")));
+ UpdateSettings updateSettings = UpdateSettings.getInstance();
+ params.put("update.channel.status", updateSettings.getSelectedChannelStatus().getCode());
+ params.put("update.ignored.builds", StringUtil.join(updateSettings.getIgnoredBuildNumbers(), ","));
- params.add(Couple.of("plugin.name", error.getPluginName()));
- params.add(Couple.of("plugin.version", error.getPluginVersion()));
+ params.put("plugin.name", error.getPluginName());
+ params.put("plugin.version", error.getPluginVersion());
- params.add(Couple.of("last.action", error.getLastAction()));
- params.add(Couple.of("previous.exception",
- error.getPreviousException() == null ? null : Integer.toString(error.getPreviousException())));
+ params.put("last.action", error.getLastAction());
+ params.put("previous.exception", error.getPreviousException() == null ? null : Integer.toString(error.getPreviousException()));
- params.add(Couple.of("error.message", error.getMessage()));
- params.add(Couple.of("error.stacktrace", error.getStackTrace()));
+ params.put("error.message", error.getMessage());
+ params.put("error.stacktrace", error.getStackTrace());
+ params.put("error.description", error.getDescription());
- params.add(Couple.of("error.description", error.getDescription()));
-
- params.add(Couple.of("assignee.id", error.getAssigneeId() == null ? null : Integer.toString(error.getAssigneeId())));
+ params.put("assignee.id", error.getAssigneeId() == null ? null : Integer.toString(error.getAssigneeId()));
for (Attachment attachment : error.getAttachments()) {
- params.add(Couple.of("attachment.name", attachment.getName()));
- params.add(Couple.of("attachment.value", attachment.getEncodedBytes()));
+ params.put("attachment.name", attachment.getName());
+ params.put("attachment.value", attachment.getEncodedBytes());
}
return params;
}
- private static String readFrom(InputStream is) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int c;
- while ((c = is.read()) != -1) {
- out.write(c);
- }
- String s = out.toString();
- out.close();
- return s;
- }
-
private static String format(Calendar calendar) {
return calendar == null ? null : Long.toString(calendar.getTime().getTime());
}
+ private static byte[] join(Map<String, String> params) throws UnsupportedEncodingException {
+ StringBuilder builder = new StringBuilder();
+ for (Map.Entry<String, String> param : params.entrySet()) {
+ if (StringUtil.isEmpty(param.getKey())) {
+ throw new IllegalArgumentException(param.toString());
+ }
+ if (builder.length() > 0) {
+ builder.append('&');
+ }
+ if (StringUtil.isNotEmpty(param.getValue())) {
+ builder.append(param.getKey()).append('=').append(URLEncoder.encode(param.getValue(), ENCODING));
+ }
+ }
+ return builder.toString().getBytes(ENCODING);
+ }
+
private static HttpURLConnection post(URL url, byte[] bytes) throws IOException {
- HttpURLConnection connection = (HttpURLConnection)HttpConfigurable.getInstance().openConnection(url.toString());
+ HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
+
+ connection.setSSLSocketFactory(ourSslContext.getSocketFactory());
+ if (!SystemInfo.isJavaVersionAtLeast("1.7") || !SystemProperties.getBooleanProperty("jsse.enableSNIExtension", true)) {
+ connection.setHostnameVerifier(new EaHostnameVerifier(url.getHost(), "ftp.intellij.net"));
+ }
- connection.setRequestMethod(HTTP_POST);
+ connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
- connection.setRequestProperty(HTTP_CONTENT_TYPE, String.format("%s; charset=%s", HTTP_WWW_FORM, ENCODING));
- connection.setRequestProperty(HTTP_CONTENT_LENGTH, Integer.toString(bytes.length));
+ connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=" + ENCODING);
+ connection.setRequestProperty("Content-Length", Integer.toString(bytes.length));
- OutputStream out = new BufferedOutputStream(connection.getOutputStream());
+ OutputStream out = connection.getOutputStream();
try {
out.write(bytes);
- out.flush();
- } finally {
+ }
+ finally {
out.close();
}
return connection;
}
- private static byte[] join(List<Couple<String>> params) throws UnsupportedEncodingException {
- StringBuilder builder = new StringBuilder();
-
- Iterator<Couple<String>> it = params.iterator();
-
- while (it.hasNext()) {
- Couple<String> param = it.next();
-
- if (StringUtil.isEmpty(param.first))
- throw new IllegalArgumentException(param.toString());
+ private synchronized static SSLContext initContext() throws GeneralSecurityException, IOException {
+ CertificateFactory cf = CertificateFactory.getInstance(CertificateUtil.X509);
+ Certificate ca = cf.generateCertificate(new ByteArrayInputStream(JB_CA_CERT.getBytes(ENCODING)));
+ KeyStore ks = KeyStore.getInstance(CertificateUtil.JKS);
+ ks.load(null, null);
+ ks.setCertificateEntry("JetBrains CA", ca);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(CertificateUtil.X509);
+ tmf.init(ks);
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(null, tmf.getTrustManagers(), null);
+ return ctx;
+ }
- if (StringUtil.isNotEmpty(param.second))
- builder.append(param.first).append("=").append(URLEncoder.encode(param.second, ENCODING));
+ private static class EaHostnameVerifier implements HostnameVerifier {
+ private final Set<String> myAllowedHosts;
- if (it.hasNext())
- builder.append(POST_DELIMITER);
+ public EaHostnameVerifier(@NotNull String... allowedHosts) {
+ myAllowedHosts = ContainerUtil.newHashSet(allowedHosts);
}
- return builder.toString().getBytes();
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ try {
+ Certificate[] certificates = session.getPeerCertificates();
+ if (certificates.length > 0) {
+ Certificate certificate = certificates[0];
+ if (certificate instanceof X509Certificate) {
+ String cn = CertificateUtil.getCommonName((X509Certificate)certificate);
+ return myAllowedHosts.contains(cn);
+ }
+ }
+ }
+ catch (SSLPeerUnverifiedException ignored) { }
+ return false;
+ }
}
+
+ @SuppressWarnings("SpellCheckingInspection") private static final String JB_CA_CERT =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFvjCCA6agAwIBAgIQMYHnK1dpIZVCoitWqBwhXjANBgkqhkiG9w0BAQsFADBn\n" +
+ "MRMwEQYKCZImiZPyLGQBGRYDTmV0MRgwFgYKCZImiZPyLGQBGRYISW50ZWxsaUox\n" +
+ "FDASBgoJkiaJk/IsZAEZFgRMYWJzMSAwHgYDVQQDExdKZXRCcmFpbnMgRW50ZXJw\n" +
+ "cmlzZSBDQTAeFw0xMjEyMjkxMDEyMzJaFw0zMjEyMjkxMDIyMzBaMGcxEzARBgoJ\n" +
+ "kiaJk/IsZAEZFgNOZXQxGDAWBgoJkiaJk/IsZAEZFghJbnRlbGxpSjEUMBIGCgmS\n" +
+ "JomT8ixkARkWBExhYnMxIDAeBgNVBAMTF0pldEJyYWlucyBFbnRlcnByaXNlIENB\n" +
+ "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzPCE2gPgKECo5CB3BTAw\n" +
+ "4XrrNpg+YwTMzeNNDYs4VdPzBq0snWsbm5qP6z1GBGUTr4agERQUxc4//gZMR0UJ\n" +
+ "89GWVNYPbZ/MrkfyaOiem8xosuZ+7WoFu4nYnKbBBMBA7S2idrPSmPv2wYiHJCY7\n" +
+ "eN2AdViiFSAUeGw/7pIgou92/4Bbm6SSzRBKBYfRIfwq0ZgETSIjhNR5o3XJB5i2\n" +
+ "CkSjMk7kNiMWBaq+Alv+Um/xMFnl5jiq9H7YAALgH/mZHr8ANniSyBwkj4r/7GQ3\n" +
+ "UIYwoLrGxSOSEY9UhEpdqQkRbSSjQiFYMlhYEAtLERK4KZObTuUgdiE6Wk38EOKZ\n" +
+ "wy1eE/EIh8vWBHFSH5opPSK4dyamxj9o5c2g1hJ07ZBUCV/nsrKb+ruMkwBfI286\n" +
+ "+HPTMUmoKuUfSfHZ5TiuF5EvcSD7Df2ZCFpRugPs26FRGvtsiBMEmu4u6fu5RNkh\n" +
+ "s7Ueq6ISblt6dj/youywiAZnyrtNKJVyK0m051g9b2IokHjrk9XTswTqBHDjZKYr\n" +
+ "YG/5jDSSzvR/ptR9YIrHF0a9A6LQLZ6ews4FUO6O/RhiYXV8FggD7ZUg019OBUx3\n" +
+ "rF1L3GBYA8YhYP/N18r8DqOaFgUiRDyeRMbka9OXZ2KJT6iL+mOfg/svSW8lc4Ly\n" +
+ "EgcyJ9sk7MRwrhlp3Kc0W7UCAwEAAaNmMGQwEwYJKwYBBAGCNxQCBAYeBABDAEEw\n" +
+ "CwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFB/HK/yYoWW9\n" +
+ "vr2XAyhcMmV3gSfGMBAGCSsGAQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBCwUAA4IC\n" +
+ "AQBnYu49dZRBK9W3voy6bgzz64sZfX51/RIA6aaoHAH3U1bC8EepChqWeRgijGCD\n" +
+ "CBvLTk7bk/7fgXPPvL+8RwYaxEewCi7t1RQKqPmNvUnEnw28OLvYLBEO7a4yeN5Y\n" +
+ "YaZwdfVH+0qMvTqMQku5p5Xx3dY+DAm4EqXEFD0svfeMJmOA+R1CIqRz1CXnN2FY\n" +
+ "A+86m7WLmGZ8oWlRUJDa1etqrE3ZxXHH/IunVJOGOfaQVkid3u3ageyUOnMw/iME\n" +
+ "7vi0UNVYVsCjXYZxrzCDLCxtguZaV4rMYvLRt1oUxZ+VnmdVa3aW0W//GQ70sqh2\n" +
+ "KQDtIF6Iumf8ya4vA0+K+AAowOSR/k4jQzlWQdZvJNMHP/Jc0OyJyHEegjtWssrS\n" +
+ "NoRtI6V4j277ugWF1Xpt1x0YxYyGSZTI4rqGLqVT8x6Llr24YaHCdp56rKWC/5ob\n" +
+ "IFZ7tJys7oQqof11ANDExrnHv/FEE39VDlfEIUVGyCpsyKbzO7MPfdOce2bIaQOS\n" +
+ "dQ76TpYClrnezikJgp9MSQmd3+ozs9w1upGynHNGNmVhzZ5sex9voWcGoyjmOFhs\n" +
+ "wg13S9Hjy3VYq8y0krRYLEGLctd4vnxWGzJzUNSnqezwHZRl4v4Ejp3dQUZP+5sY\n" +
+ "1F81Vj1G264YnZAcWp5x3GTI4K6+k9Xx3pwUPcKOYdlpZQ==\n" +
+ "-----END CERTIFICATE-----\n";
}
diff --git a/platform/platform-impl/src/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java b/platform/platform-impl/src/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java
index 21a44f1c6718..78b13aa63940 100644
--- a/platform/platform-impl/src/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java
+++ b/platform/platform-impl/src/com/intellij/featureStatistics/FeatureUsageTrackerImpl.java
@@ -15,10 +15,7 @@
*/
package com.intellij.featureStatistics;
-import com.intellij.openapi.components.PersistentStateComponent;
-import com.intellij.openapi.components.State;
-import com.intellij.openapi.components.Storage;
-import com.intellij.openapi.components.StoragePathMacros;
+import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
@@ -30,9 +27,9 @@ import java.util.Set;
@SuppressWarnings({"NonPrivateFieldAccessedInSynchronizedContext"})
@State(
- name = "FeatureUsageStatistics",
- storages = {@Storage(
- file = StoragePathMacros.APP_CONFIG + "/feature.usage.statistics.xml")})
+ name = "FeatureUsageStatistics",
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/feature.usage.statistics.xml", roamingType = RoamingType.DISABLED)}
+)
public class FeatureUsageTrackerImpl extends FeatureUsageTracker implements PersistentStateComponent<Element> {
private static final int HOUR = 1000 * 60 * 60;
private static final long DAY = HOUR * 24;
@@ -94,7 +91,7 @@ public class FeatureUsageTrackerImpl extends FeatureUsageTracker implements Pers
if (descriptor != null && System.currentTimeMillis() - descriptor.getLastTimeUsed() > 10 * DAY) {
return true;
}
-
+
return isToBeShown(featureId, project, HOUR);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ApplicationLoadListener.java b/platform/platform-impl/src/com/intellij/ide/ApplicationLoadListener.java
index f1d11ff938d9..b1432f87e10d 100644
--- a/platform/platform-impl/src/com/intellij/ide/ApplicationLoadListener.java
+++ b/platform/platform-impl/src/com/intellij/ide/ApplicationLoadListener.java
@@ -17,9 +17,10 @@ package com.intellij.ide;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.extensions.ExtensionPointName;
+import org.jetbrains.annotations.NotNull;
public interface ApplicationLoadListener {
ExtensionPointName<ApplicationLoadListener> EP_NAME = ExtensionPointName.create("com.intellij.ApplicationLoadListener");
- void beforeApplicationLoaded(Application application);
+ void beforeApplicationLoaded(@NotNull Application application);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
index c288150bd7ab..293c4a55eeae 100644
--- a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
+++ b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java
@@ -141,7 +141,7 @@ public class CommandLineProcessor {
starter instanceof ApplicationStarterEx &&
((ApplicationStarterEx)starter).canProcessExternalCommandLine()) {
LOG.info("Processing command with " + starter);
- ((ApplicationStarterEx) starter).processExternalCommandLine(ArrayUtil.toStringArray(args));
+ ((ApplicationStarterEx) starter).processExternalCommandLine(ArrayUtil.toStringArray(args), currentDirectory);
return null;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
index 4189b6adf98b..59b115a43105 100644
--- a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
@@ -34,17 +34,14 @@ import org.jetbrains.annotations.Nullable;
*/
@State(
name = "RecentDirectoryProjectsManager",
- roamingType = RoamingType.DISABLED,
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/other.xml"
- )}
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml", roamingType = RoamingType.DISABLED)}
)
public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase {
public RecentDirectoryProjectsManager(MessageBus messageBus) {
super(messageBus);
}
+ @Override
@Nullable
protected String getProjectPath(@NotNull Project project) {
final ProjectBaseDirectory baseDir = ProjectBaseDirectory.getInstance(project);
@@ -52,6 +49,7 @@ public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase {
return baseDirVFile != null ? FileUtil.toSystemDependentName(baseDirVFile.getPath()) : null;
}
+ @Override
protected void doOpenProject(@NotNull String projectPath, Project projectToClose, boolean forceOpenInNewFrame) {
final VirtualFile projectDir = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(projectPath));
if (projectDir != null) {
diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
index 1a6bffbcd297..7991c3af0104 100644
--- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
@@ -86,6 +86,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
messageBus.connect().subscribe(AppLifecycleListener.TOPIC, new MyAppLifecycleListener());
}
+ @Override
public State getState() {
synchronized (myStateLock) {
myState.validateRecentProjects();
@@ -93,6 +94,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
}
}
+ @Override
public void loadState(final State state) {
synchronized (myStateLock) {
myState = state;
@@ -212,7 +214,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
if (addClearListItem) {
AnAction clearListAction = new DumbAwareAction(IdeBundle.message("action.clear.list")) {
@Override
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
String message = IdeBundle.message("action.clear.list.message");
String title = IdeBundle.message("action.clear.list.title");
if (Messages.showOkCancelDialog(e.getProject(), message, title, Messages.getQuestionIcon()) == Messages.OK) {
@@ -249,6 +251,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
return file.exists() && (!file.isDirectory() || new File(file, Project.DIRECTORY_STORE_FOLDER).exists());
}
+ @Override
public void projectOpened(final Project project) {
String path = getProjectPath(project);
if (path != null) {
@@ -269,6 +272,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
}
}
+ @Override
public void projectClosed(final Project project) {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length > 0) {
@@ -347,6 +351,7 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
}
private class MyAppLifecycleListener extends AppLifecycleListener.Adapter {
+ @Override
public void appFrameCreated(final String[] commandLineArgs, @NotNull final Ref<Boolean> willOpenProject) {
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
ProjectManager.getInstance().addProjectManagerListener(RecentProjectsManagerBase.this);
@@ -356,19 +361,23 @@ public abstract class RecentProjectsManagerBase implements ProjectManagerListene
}
}
+ @Override
public void appStarting(Project projectFromCommandLine) {
if (projectFromCommandLine != null) return;
doReopenLastProject();
}
+ @Override
public void projectFrameClosed() {
updateLastProjectPath();
}
+ @Override
public void projectOpenFailed() {
updateLastProjectPath();
}
+ @Override
public void appClosing() {
updateLastProjectPath();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java
index e0c9373bbf2b..43cc4d0be9d8 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutAction.java
@@ -16,6 +16,7 @@
package com.intellij.ide.actions;
import com.intellij.ide.DataManager;
+import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -31,7 +32,7 @@ import java.awt.*;
public class AboutAction extends AnAction implements DumbAware {
@Override
public void update(AnActionEvent e) {
- e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu);
+ e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu || !ActionPlaces.MAIN_MENU.equals(e.getPlace()));
e.getPresentation().setDescription("Show information about " + ApplicationNamesInfo.getInstance().getFullProductName());
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AssociateFileType.java b/platform/platform-impl/src/com/intellij/ide/actions/AssociateFileType.java
index 77544ae1d14c..8b1375d9f933 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/AssociateFileType.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/AssociateFileType.java
@@ -41,7 +41,7 @@ public class AssociateFileType extends AnAction {
// the action should also be available for files which have been auto-detected as text or as a particular language (IDEA-79574)
haveSmthToDo = FileTypeManager.getInstance().getFileTypeByFileName(file.getName()) == FileTypes.UNKNOWN;
}
- presentation.setVisible(haveSmthToDo || ActionPlaces.MAIN_MENU.equals(e.getPlace()));
+ presentation.setVisible(haveSmthToDo || ActionPlaces.isMainMenuOrActionSearch(e.getPlace()));
presentation.setEnabled(haveSmthToDo);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java
index 442d09b8b3bd..505d0f5eef3d 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.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.
@@ -39,6 +39,7 @@ import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IconUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -53,11 +54,11 @@ import java.io.File;
public abstract class BaseShowRecentFilesAction extends AnAction implements DumbAware {
private static final Color BORDER_COLOR = Gray._135;
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
show(CommonDataKeys.PROJECT.getData(e.getDataContext()));
}
- public void update(AnActionEvent event){
+ public void update(@NotNull AnActionEvent event){
Presentation presentation = event.getPresentation();
Project project = CommonDataKeys.PROJECT.getData(event.getDataContext());
presentation.setEnabled(project != null);
@@ -93,7 +94,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
final JList list = new JBList(model);
list.addKeyListener(
new KeyAdapter() {
- public void keyPressed(KeyEvent e) {
+ public void keyPressed(@NotNull KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
int index = list.getSelectedIndex();
if (index == -1 || index >= list.getModel().getSize()){
@@ -150,7 +151,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
JPanel footerPanel = new JPanel(new BorderLayout()) {
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
super.paintComponent(g);
g.setColor(BORDER_COLOR);
g.drawLine(0, 0, getWidth(), 0);
@@ -237,7 +238,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
}
@Override
- public void actionPerformed(ActionEvent e) {
+ public void actionPerformed(@NotNull ActionEvent e) {
if (myPopup != null) {
myPopup.cancel();
}
@@ -272,7 +273,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb
return fullText;
}
- public void valueChanged(final ListSelectionEvent e) {
+ public void valueChanged(@NotNull final ListSelectionEvent e) {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
index 411f2d9d93bb..0b696c8f4496 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
@@ -134,12 +134,12 @@ public class CreateLauncherScriptAction extends DumbAwareAction {
private static File createLauncherScriptFile() throws IOException, ExecutionException {
String runPath = PathManager.getHomePath();
+ final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase();
if (!SystemInfo.isMac) {
// for Macs just use "*.app"
- final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase();
runPath += "/bin/" + productName + ".sh";
} else if (runPath.endsWith(CONTENTS)) {
- runPath = runPath.substring(0, runPath.length() - CONTENTS.length());
+ runPath += "/MacOS/" + productName;
}
String launcherContents = ExecUtil.loadTemplate(CreateLauncherScriptAction.class.getClassLoader(), "launcher.py",
newHashMap(asList("$CONFIG_PATH$", "$RUN_PATH$"),
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExitAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ExitAction.java
index 52487a57f9f2..3017b8624828 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ExitAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ExitAction.java
@@ -16,6 +16,7 @@
*/
package com.intellij.ide.actions;
+import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
@@ -24,7 +25,7 @@ import com.intellij.openapi.util.SystemInfo;
public class ExitAction extends AnAction implements DumbAware {
public void update(AnActionEvent e) {
- e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu);
+ e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu || !ActionPlaces.MAIN_MENU.equals(e.getPlace()));
}
public void actionPerformed(AnActionEvent e) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OccurenceNavigatorActionBase.java b/platform/platform-impl/src/com/intellij/ide/actions/OccurenceNavigatorActionBase.java
index f2314a728913..c7ae78f0cd59 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OccurenceNavigatorActionBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OccurenceNavigatorActionBase.java
@@ -68,14 +68,14 @@ abstract class OccurenceNavigatorActionBase extends AnAction implements DumbAwar
if (project == null) {
presentation.setEnabled(false);
// make it invisible only in main menu to avoid initial invisibility in toolbars
- presentation.setVisible(!ActionPlaces.MAIN_MENU.equals(event.getPlace()));
+ presentation.setVisible(!ActionPlaces.isMainMenuOrActionSearch(event.getPlace()));
return;
}
OccurenceNavigator navigator = getNavigator(event.getDataContext());
if (navigator == null) {
presentation.setEnabled(false);
// make it invisible only in main menu to avoid initial invisibility in toolbars
- presentation.setVisible(!ActionPlaces.MAIN_MENU.equals(event.getPlace()));
+ presentation.setVisible(!ActionPlaces.isMainMenuOrActionSearch(event.getPlace()));
return;
}
presentation.setVisible(true);
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java b/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java
index ddfc1a3989aa..560082bf9e64 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/PinActiveTabAction.java
@@ -116,12 +116,17 @@ public class PinActiveTabAction extends ToggleAction implements DumbAware {
super.update(e);
Presentation presentation = e.getPresentation();
DataContext context = e.getDataContext();
- if (getFile(context) != null) {
- presentation.setEnabledAndVisible(true);
- }
- else {
- Content content = getContent(context);
- presentation.setEnabledAndVisible(content != null && content.isPinnable());
+ EditorWindow window = getEditorWindow(context);
+ if (window == null || window.getOwner().isPreview()) {
+ presentation.setEnabledAndVisible(false);
+ } else {
+ if (getFile(context) != null) {
+ presentation.setEnabledAndVisible(true);
+ }
+ else {
+ Content content = getContent(context);
+ presentation.setEnabledAndVisible(content != null && content.isPinnable());
+ }
}
if (ActionPlaces.EDITOR_TAB_POPUP.equals(e.getPlace()) ||
ViewContext.CELL_POPUP_PLACE.equals(e.getPlace())) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
index 59ac567af38a..abd875af728f 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.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.
@@ -25,13 +25,14 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public class ShowRecentFilesAction extends DumbAwareAction {
@Override
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
if (project != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.recent.files");
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java
index eda6ec9f2d7c..5ced3f0db498 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java
@@ -34,7 +34,7 @@ public class ShowSettingsAction extends AnAction implements DumbAware {
@Override
public void update(AnActionEvent e) {
- if (SystemInfo.isMac && e.getPlace().equals(ActionPlaces.MAIN_MENU)) {
+ if (SystemInfo.isMac && ActionPlaces.isMainMenuOrActionSearch(e.getPlace())) {
// It's called from Preferences in App menu.
e.getPresentation().setVisible(false);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
index 2c5cc5b02282..8d6f806802c2 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java
@@ -75,7 +75,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil {
new IdeConfigurablesGroup()};
return Registry.is("ide.new.settings.dialog")
- ? MixedConfigurableGroup.getGroups(getConfigurables(groups, true))
+ ? new ConfigurableGroup[]{new SortedConfigurableGroup(getConfigurables(groups, true))}
: groups;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SplitAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SplitAction.java
index fb55f3649484..9e9a349bb3fd 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SplitAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SplitAction.java
@@ -60,7 +60,8 @@ public abstract class SplitAction extends AnAction implements DumbAware {
final int minimum = myCloseSource ? 2 : 1;
final boolean enabled = project != null
&& window != null
- && window.getTabCount() >= minimum;
+ && window.getTabCount() >= minimum
+ && !window.getOwner().isPreview();
event.getPresentation().setEnabled(enabled);
}
}
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 cb35b5a504f9..cecf0f60a803 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -94,7 +94,7 @@ public class Switcher extends AnAction implements DumbAware {
public void run() {
synchronized (Switcher.class) {
if (SWITCHER != null) {
- SWITCHER.navigate();
+ SWITCHER.navigate(false);
}
}
}
@@ -135,7 +135,7 @@ public class Switcher extends AnAction implements DumbAware {
@NonNls private static final String SWITCHER_TITLE = "Switcher";
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) return;
@@ -200,7 +200,7 @@ public class Switcher extends AnAction implements DumbAware {
jList.setSelectedIndex(jList.getAnchorSelectionIndex());
}
if (jList.getSelectedIndex() != -1) {
- navigate();
+ navigate(false);
}
}
return true;
@@ -226,7 +226,7 @@ public class Switcher extends AnAction implements DumbAware {
descriptions = new JPanel(new BorderLayout()) {
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
super.paintComponent(g);
g.setColor(UIUtil.isUnderDarcula() ? SEPARATOR_COLOR : BORDER_COLOR);
g.drawLine(0, 0, getWidth(), 0);
@@ -249,7 +249,7 @@ public class Switcher extends AnAction implements DumbAware {
final Map<ToolWindow, String> map = ContainerUtil.reverseMap(twShortcuts);
Collections.sort(windows, new Comparator<ToolWindow>() {
@Override
- public int compare(ToolWindow o1, ToolWindow o2) {
+ public int compare(@NotNull ToolWindow o1, @NotNull ToolWindow o2) {
return StringUtil.compare(map.get(o1), map.get(o2), false);
}
});
@@ -297,7 +297,7 @@ public class Switcher extends AnAction implements DumbAware {
toolWindows.addMouseMotionListener(this);
myClickListener.installOn(toolWindows);
toolWindows.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
+ public void valueChanged(@NotNull ListSelectionEvent e) {
if (!toolWindows.isSelectionEmpty() && !files.isSelectionEmpty()) {
files.clearSelection();
}
@@ -306,7 +306,7 @@ public class Switcher extends AnAction implements DumbAware {
separator = new JPanel() {
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
super.paintComponent(g);
g.setColor(SEPARATOR_COLOR);
g.drawLine(0, 0, 0, getHeight());
@@ -374,7 +374,7 @@ public class Switcher extends AnAction implements DumbAware {
JPanel myPanel = new JPanel(new BorderLayout());
JLabel myLabel = new JLabel() {
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
GraphicsConfig config = new GraphicsConfig(g);
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
super.paintComponent(g);
@@ -425,7 +425,7 @@ public class Switcher extends AnAction implements DumbAware {
return fullText;
}
- public void valueChanged(final ListSelectionEvent e) {
+ public void valueChanged(@NotNull final ListSelectionEvent e) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
updatePathLabel();
@@ -466,7 +466,7 @@ public class Switcher extends AnAction implements DumbAware {
files.setSelectionMode(pinned ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION);
files.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
+ public void valueChanged(@NotNull ListSelectionEvent e) {
if (!files.isSelectionEmpty() && !toolWindows.isSelectionEmpty()) {
toolWindows.getSelectionModel().clearSelection();
}
@@ -526,21 +526,21 @@ public class Switcher extends AnAction implements DumbAware {
if (isPinnedMode()) {
new AnAction(null ,null ,null) {
@Override
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
changeSelection();
}
}.registerCustomShortcutSet(CustomShortcutSet.fromString("TAB"), this, myPopup);
new AnAction(null, null, null) {
@Override
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
//suppress all actions to activate a toolwindow : IDEA-71277
}
}.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup);
new AnAction(null, null, null) {
@Override
- public void actionPerformed(AnActionEvent e) {
+ public void actionPerformed(@NotNull AnActionEvent e) {
if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) {
mySpeedSearch.hidePopup();
} else {
@@ -590,24 +590,24 @@ public class Switcher extends AnAction implements DumbAware {
return ((KeyboardShortcut)shortcutSet.getShortcuts()[0]).getFirstKeyStroke().getModifiers();
}
- public void keyTyped(KeyEvent e) {
+ public void keyTyped(@NotNull KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
- if ((e.getKeyCode() == CTRL_KEY && isAutoHide())
- || e.getKeyCode() == VK_ENTER) {
- navigate();
- } else
- if (e.getKeyCode() == VK_LEFT) {
+ if (e.getKeyCode() == CTRL_KEY && isAutoHide() || e.getKeyCode() == VK_ENTER) {
+ navigate(e.isShiftDown());
+ }
+ else if (e.getKeyCode() == VK_LEFT) {
goLeft();
- } else if (e.getKeyCode() == VK_RIGHT) {
+ }
+ else if (e.getKeyCode() == VK_RIGHT) {
goRight();
}
}
KeyEvent lastEvent;
- public void keyPressed(KeyEvent e) {
- if ((mySpeedSearch != null && mySpeedSearch.isPopupActive()) || lastEvent == e) return;
+ public void keyPressed(@NotNull KeyEvent e) {
+ if (mySpeedSearch != null && mySpeedSearch.isPopupActive() || lastEvent == e) return;
lastEvent = e;
switch (e.getKeyCode()) {
case VK_UP:
@@ -668,7 +668,7 @@ public class Switcher extends AnAction implements DumbAware {
if (value instanceof FileInfo) {
final FileInfo info = (FileInfo)value;
final VirtualFile virtualFile = info.first;
- final FileEditorManagerImpl editorManager = ((FileEditorManagerImpl)FileEditorManager.getInstance(project));
+ final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project);
final JList jList = getSelectedList();
final EditorWindow wnd = findAppropriateWindow(info);
if (wnd == null) {
@@ -836,7 +836,7 @@ public class Switcher extends AnAction implements DumbAware {
}
}
- void navigate() {
+ void navigate(final boolean openInNewWindow) {
final Object[] values = getSelectedList().getSelectedValues();
myPopup.closeOk(null);
if (values.length > 0 && values[0] instanceof ToolWindow) {
@@ -850,14 +850,19 @@ public class Switcher extends AnAction implements DumbAware {
if (value instanceof FileInfo) {
final FileInfo info = (FileInfo)value;
- if (info.second != null) {
+ VirtualFile file = info.first;
+ if (openInNewWindow) {
+ manager.openFileInNewWindow(file);
+ }
+ else if (info.second != null) {
EditorWindow wnd = findAppropriateWindow(info);
if (wnd != null) {
- manager.openFileImpl2(wnd, info.first, true);
- manager.addSelectionRecord(info.first, wnd);
+ manager.openFileImpl2(wnd, file, true);
+ manager.addSelectionRecord(file, wnd);
}
- } else {
- manager.openFile(info.first, true, true);
+ }
+ else {
+ manager.openFile(file, true, true);
}
}
}
@@ -873,13 +878,13 @@ public class Switcher extends AnAction implements DumbAware {
return ArrayUtil.contains(info.second, windows) ? info.second : windows.length > 0 ? windows[0] : null;
}
- public void mouseClicked(MouseEvent e) {
+ public void mouseClicked(@NotNull MouseEvent e) {
}
private boolean mouseMovedFirstTime = true;
private JList mouseMoveSrc = null;
private int mouseMoveListIndex = -1;
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(@NotNull MouseEvent e) {
if (mouseMovedFirstTime) {
mouseMovedFirstTime = false;
return;
@@ -907,15 +912,15 @@ public class Switcher extends AnAction implements DumbAware {
files.repaint();
}
- public void mousePressed(MouseEvent e) {}
- public void mouseReleased(MouseEvent e) {}
- public void mouseEntered(MouseEvent e) {}
- public void mouseExited(MouseEvent e) {
+ public void mousePressed(@NotNull MouseEvent e) {}
+ public void mouseReleased(@NotNull MouseEvent e) {}
+ public void mouseEntered(@NotNull MouseEvent e) {}
+ public void mouseExited(@NotNull MouseEvent e) {
mouseMoveSrc = null;
mouseMoveListIndex = -1;
repaintLists();
}
- public void mouseDragged(MouseEvent e) {}
+ public void mouseDragged(@NotNull MouseEvent e) {}
private class SwitcherSpeedSearch extends SpeedSearchBase<SwitcherPanel> implements PropertyChangeListener {
private Object[] myElements;
@@ -1031,7 +1036,7 @@ public class Switcher extends AnAction implements DumbAware {
}
@Override
- public void propertyChange(PropertyChangeEvent evt) {
+ public void propertyChange(@NotNull PropertyChangeEvent evt) {
final MyList list = getSelectedList();
final Object value = list.getSelectedValue();
if (project.isDisposed()) {
@@ -1068,7 +1073,7 @@ public class Switcher extends AnAction implements DumbAware {
private Rectangle dBounds;
@Override
- public void layoutContainer(Container target) {
+ public void layoutContainer(@NotNull Container target) {
final JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, files);
JComponent filesPane = scrollPane != null ? scrollPane : files;
if (sBounds == null || !target.isShowing()) {
@@ -1142,7 +1147,7 @@ public class Switcher extends AnAction implements DumbAware {
}
@Override
- public void processKeyEvent(KeyEvent e) {
+ public void processKeyEvent(@NotNull KeyEvent e) {
super.processKeyEvent(e);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
index af3c193ca9d9..04beaa0f370e 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
@@ -182,9 +182,21 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
}
@Override
+ public void doCancelAction() {
+ doOKAction();
+ }
+
+ @Override
protected void doOKAction() {
for (AbstractCustomizeWizardStep step : mySteps) {
- if (!step.beforeOkAction()) return;
+ if (!step.beforeOkAction()) {
+ int index = mySteps.indexOf(step);
+ if (myIndex != index) {
+ myIndex = index;
+ initCurrentStep(true);
+ }
+ return;
+ }
}
super.doOKAction();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/aware/DnDAwareTree.java b/platform/platform-impl/src/com/intellij/ide/dnd/aware/DnDAwareTree.java
index e871ff1872c2..7411c70e5984 100644
--- a/platform/platform-impl/src/com/intellij/ide/dnd/aware/DnDAwareTree.java
+++ b/platform/platform-impl/src/com/intellij/ide/dnd/aware/DnDAwareTree.java
@@ -19,6 +19,7 @@ import com.intellij.ide.dnd.DnDAware;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.ui.JBSwingUtilities;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.util.ui.tree.WideSelectionTreeUI;
@@ -54,7 +55,7 @@ public class DnDAwareTree extends Tree implements DnDAware {
@Override
protected void processMouseMotionEvent(MouseEvent e) {
- if (SystemInfo.isMac && SwingUtilities.isRightMouseButton(e) && e.getID() == MouseEvent.MOUSE_DRAGGED) return;
+ if (SystemInfo.isMac && JBSwingUtilities.isRightMouseButton(e) && e.getID() == MouseEvent.MOUSE_DRAGGED) return;
super.processMouseMotionEvent(e);
}
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 de5d67b5e2d8..4d3a502c253e 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
@@ -193,7 +193,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
return myKey.get().get();
}
- }, project == null ? Condition.FALSE : project.getDisposed());
+ }, project == null ? Conditions.alwaysFalse() : project.getDisposed());
if (key instanceof byte[]) return (byte[])key;
if (key instanceof PasswordSafeException) throw (PasswordSafeException)key;
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
index 57329fb8fe9d..e88a17416fc1 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManager.java
@@ -183,6 +183,7 @@ public class PluginManager extends PluginManagerCore {
}
else if (myPlugins2Enable != null && ENABLE.equals(description)) {
disabledPlugins.removeAll(myPlugins2Enable);
+ PluginManagerMain.notifyPluginsWereUpdated("Changes were applied", null);
}
try {
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
index cc6e16aba6c2..9accbc5bc6c8 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
@@ -174,6 +174,9 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
update |= settings.SHOW_EDITOR_TOOLTIP != myComponent.myEditorTooltipCheckBox.isSelected();
settings.SHOW_EDITOR_TOOLTIP = myComponent.myEditorTooltipCheckBox.isSelected();
+ update |= settings.NAVIGATE_TO_PREVIEW != myComponent.myNavigateToPreviewCheckBox.isSelected();
+ settings.NAVIGATE_TO_PREVIEW = myComponent.myNavigateToPreviewCheckBox.isSelected();
+
update |= settings.DISABLE_MNEMONICS_IN_CONTROLS != myComponent.myDisableMnemonicInControlsCheckBox.isSelected();
settings.DISABLE_MNEMONICS_IN_CONTROLS = myComponent.myDisableMnemonicInControlsCheckBox.isSelected();
@@ -280,6 +283,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
myComponent.myLeftLayoutCheckBox.setSelected(settings.LEFT_HORIZONTAL_SPLIT);
myComponent.myRightLayoutCheckBox.setSelected(settings.RIGHT_HORIZONTAL_SPLIT);
myComponent.myEditorTooltipCheckBox.setSelected(settings.SHOW_EDITOR_TOOLTIP);
+ myComponent.myNavigateToPreviewCheckBox.setSelected(settings.NAVIGATE_TO_PREVIEW);
myComponent.myDisableMnemonicInControlsCheckBox.setSelected(settings.DISABLE_MNEMONICS_IN_CONTROLS);
boolean alphaModeEnabled = WindowManagerEx.getInstanceEx().isAlphaModeSupported();
@@ -325,6 +329,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
isModified |= myComponent.myLeftLayoutCheckBox.isSelected() != settings.LEFT_HORIZONTAL_SPLIT;
isModified |= myComponent.myRightLayoutCheckBox.isSelected() != settings.RIGHT_HORIZONTAL_SPLIT;
isModified |= myComponent.myEditorTooltipCheckBox.isSelected() != settings.SHOW_EDITOR_TOOLTIP;
+ isModified |= myComponent.myNavigateToPreviewCheckBox.isSelected() != settings.NAVIGATE_TO_PREVIEW;
isModified |= myComponent.myHideIconsInQuickNavigation.isSelected() != settings.SHOW_ICONS_IN_QUICK_NAVIGATION;
@@ -397,6 +402,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
private JSlider myInitialTooltipDelaySlider;
private ComboBox myPresentationModeFontSize;
private JCheckBox myEditorTooltipCheckBox;
+ private JCheckBox myNavigateToPreviewCheckBox;
private JCheckBox myAllowStatusBar;
private JCheckBox myAllowLineNumbers;
private JCheckBox myAllowAnnotations;
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
index 550e8e2482e1..7590feba2ad8 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
+++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form
@@ -401,6 +401,14 @@
<text resource-bundle="messages/IdeBundle" key="checkbox.show.editor.preview.popup"/>
</properties>
</component>
+ <component id="3e39" class="javax.swing.JCheckBox" binding="myNavigateToPreviewCheckBox" default-binding="true">
+ <constraints>
+ <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/IdeBundle" key="checkbox.use.preview.window"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="e3cc0" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
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 1036307e97d7..7e00dc3a9841 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
@@ -87,9 +87,8 @@ import java.util.List;
*/
@State(
name = "LafManager",
- roamingType = RoamingType.PER_PLATFORM,
- storages = {@Storage(
- file = StoragePathMacros.APP_CONFIG + "/options.xml")})
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/options.xml", roamingType = RoamingType.PER_PLATFORM)}
+)
public final class LafManagerImpl extends LafManager implements ApplicationComponent, PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.ui.LafManager");
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
index f721abfdb92b..ef0a4214db11 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf.properties
@@ -118,6 +118,7 @@ CheckBox.darcula.focused.backgroundColor2.selected=3B98FB
ComboBoxUI=com.intellij.ide.ui.laf.darcula.ui.DarculaComboBoxUI
ComboBox.disabledBackground=e8e8e8
+ComboBox.disabledForeground=777777
ComboBox.squareButton=false
ComboBox.darcula.arrowFillColor=6e9bd5
ComboBox.darcula.arrowFocusedFillColor=2d82ed
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java
index 8febc9ad392a..a0df30abae1c 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/search/SearchUtil.java
@@ -41,8 +41,6 @@ import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.*;
@@ -314,18 +312,6 @@ public class SearchUtil {
}
}
- public static Runnable lightOptions(final SearchableConfigurable configurable,
- final JComponent component,
- final String option,
- final GlassPanel glassPanel,
- final boolean forceSelect) {
- return new Runnable() {
- public void run() {
- traverseComponentsTree(configurable, glassPanel, component, option, forceSelect);
- }
- };
- }
-
public static String markup(@NonNls @NotNull String textToMarkup, @Nullable String filter) {
if (filter == null || filter.length() == 0) {
return textToMarkup;
@@ -575,80 +561,6 @@ public class SearchUtil {
return null;
}
- public static void showHintPopup(final ConfigurableSearchTextField searchField,
- final JBPopup[] activePopup,
- final Alarm showHintAlarm,
- final Consumer<String> selectConfigurable,
- final Project project) {
- for (JBPopup aPopup : activePopup) {
- if (aPopup != null) {
- aPopup.cancel();
- }
- }
-
- final JBPopup popup = createPopup(searchField, activePopup, showHintAlarm, selectConfigurable, project, 0); //no selection
- if (popup != null) {
- popup.showUnderneathOf(searchField);
- searchField.requestFocusInWindow();
- }
-
- activePopup[0] = popup;
- activePopup[1] = null;
- }
-
-
- public static void registerKeyboardNavigation(final ConfigurableSearchTextField searchField,
- final JBPopup[] activePopup,
- final Alarm showHintAlarm,
- final Consumer<String> selectConfigurable,
- final Project project) {
- final Consumer<Integer> shower = new Consumer<Integer>() {
- public void consume(final Integer direction) {
- if (activePopup[0] != null) {
- activePopup[0].cancel();
- }
-
- if (activePopup[1] != null && activePopup[1].isVisible()) {
- return;
- }
-
- final JBPopup popup = createPopup(searchField, activePopup, showHintAlarm, selectConfigurable, project, direction.intValue());
- if (popup != null) {
- popup.showUnderneathOf(searchField);
- }
- activePopup[0] = null;
- activePopup[1] = popup;
- }
- };
- searchField.registerKeyboardAction(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- shower.consume(1);
- }
- }, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
- searchField.registerKeyboardAction(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- shower.consume(-1);
- }
- }, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
-
- searchField.addKeyboardListener(new KeyAdapter() {
- public void keyPressed(KeyEvent e) {
- if (e.getKeyCode() == KeyEvent.VK_ESCAPE && searchField.getText().length() > 0) {
- e.consume();
- if (cancelPopups(activePopup)) return;
- searchField.setText("");
- }
- else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
- searchField.addCurrentTextToHistory();
- cancelPopups(activePopup);
- if (e.getModifiers() == 0) {
- e.consume();
- }
- }
- }
- });
- }
-
private static boolean cancelPopups(final JBPopup[] activePopup) {
for (JBPopup popup : activePopup) {
if (popup != null && popup.isVisible()) {
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ProjectPropertiesComponentImpl.java b/platform/platform-impl/src/com/intellij/ide/util/ProjectPropertiesComponentImpl.java
index e44921e6d5df..4b11b44b2bc9 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ProjectPropertiesComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ProjectPropertiesComponentImpl.java
@@ -15,15 +15,13 @@
*/
package com.intellij.ide.util;
-import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
@State(
- name = "PropertiesComponent",
- roamingType = RoamingType.DISABLED,
- storages = {@Storage(
- file = StoragePathMacros.WORKSPACE_FILE)})
+ name = "PropertiesComponent",
+ storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}
+)
public class ProjectPropertiesComponentImpl extends PropertiesComponentImpl {
}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/UsageTrigger.java b/platform/platform-impl/src/com/intellij/internal/statistic/UsageTrigger.java
index 40282a89eded..99e62b9da292 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/UsageTrigger.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/UsageTrigger.java
@@ -34,7 +34,10 @@ import java.util.Set;
/**
* User: ksafonov
*/
-@State(name = "UsageTrigger", roamingType = RoamingType.DISABLED, storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/statistics.application.usages.xml")})
+@State(
+ name = "UsageTrigger",
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/statistics.application.usages.xml", roamingType = RoamingType.DISABLED)}
+)
public class UsageTrigger implements PersistentStateComponent<UsageTrigger.State> {
public static class State {
@@ -72,7 +75,7 @@ public class UsageTrigger implements PersistentStateComponent<UsageTrigger.State
myState = state;
}
-
+
public static class MyCollector extends UsagesCollector {
private static final GroupDescriptor GROUP = GroupDescriptor.create("features counts", GroupDescriptor.HIGHER_PRIORITY);
@@ -92,5 +95,5 @@ public class UsageTrigger implements PersistentStateComponent<UsageTrigger.State
return GROUP;
}
}
-
+
}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java
index becc1d3699a0..3acca5fffe96 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/ApplicationStatisticsPersistenceComponent.java
@@ -43,11 +43,7 @@ import java.util.Set;
@State(
name = "StatisticsApplicationUsages",
- roamingType = RoamingType.DISABLED,
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/statistics.application.usages.xml"
- )}
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/statistics.application.usages.xml", roamingType = RoamingType.DISABLED)}
)
public class ApplicationStatisticsPersistenceComponent extends ApplicationStatisticsPersistence
implements ApplicationComponent, PersistentStateComponent<Element> {
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java
index 65298387a902..d60be232c9ea 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/UsageStatisticsPersistenceComponent.java
@@ -35,11 +35,7 @@ import java.util.Set;
@State(
name = "UsagesStatistic",
- roamingType = RoamingType.DISABLED,
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/usage.statistics.xml"
- )}
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/usage.statistics.xml", roamingType = RoamingType.DISABLED)}
)
public class UsageStatisticsPersistenceComponent extends BasicSentUsagesPersistenceComponent
implements NamedComponent, PersistentStateComponent<Element> {
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 2d6a768a92c2..50ca0941f621 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
@@ -125,6 +125,7 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable
public NotificationsTable() {
super(new NotificationsTableModel());
+ setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final TableColumn idColumn = getColumnModel().getColumn(ID_COLUMN);
idColumn.setPreferredWidth(200);
@@ -151,7 +152,7 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable
displayTypeColumn.setCellRenderer(new ComboBoxTableRenderer<NotificationDisplayType>(NotificationDisplayType.values()) {
@Override
protected void customizeComponent(NotificationDisplayType value, JTable table, boolean isSelected) {
- super.customizeComponent(value, table, isSelected);
+ super.customizeComponent(myDisplayBalloons.isSelected() ? value : NotificationDisplayType.NONE, table, isSelected);
if (!myDisplayBalloons.isSelected() && !isSelected) {
setBackground(UIUtil.getComboBoxDisabledBackground());
setForeground(UIUtil.getComboBoxDisabledForeground());
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java
index b5027fd9df81..3b0e247180b2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java
@@ -55,6 +55,13 @@ public abstract class ComputableActionGroup extends ActionGroup implements DumbA
protected abstract CachedValueProvider<AnAction[]> createChildrenProvider(@NotNull ActionManager actionManager);
public abstract static class Simple extends ComputableActionGroup {
+ protected Simple() {
+ }
+
+ protected Simple(boolean popup) {
+ super(popup);
+ }
+
@NotNull
@Override
protected final CachedValueProvider<AnAction[]> createChildrenProvider(@NotNull final ActionManager actionManager) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
index bf7c79695c94..eb9436481767 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
@@ -70,10 +70,10 @@ public class QuickListsManager implements ExportableApplicationComponent, NamedJ
return loadListFromDocument(schemeContent);
}
- public Document writeScheme(@NotNull final QuickList scheme) throws WriteExternalException {
+ public Element writeScheme(@NotNull final QuickList scheme) throws WriteExternalException {
Element element = new Element(LIST_TAG);
scheme.writeExternal(element);
- return new Document(element);
+ return element;
}
public boolean shouldBeSaved(@NotNull final QuickList scheme) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
index 0d116c7a927f..fd96e54fc98e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
@@ -31,11 +31,7 @@ import java.util.*;
*/
@State(
name = "AbbreviationManager",
- roamingType = RoamingType.PER_PLATFORM,
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/abbreviations.xml"
- )}
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/abbreviations.xml", roamingType = RoamingType.PER_PLATFORM)}
)
public class AbbreviationManagerImpl extends AbbreviationManager implements
ExportableComponent, PersistentStateComponent<Element> {
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
index c5a9b01c4d21..32e823bd9758 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
@@ -70,6 +70,7 @@ import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
+import java.util.concurrent.Future;
public final class ActionManagerImpl extends ActionManagerEx implements ApplicationComponent {
@NonNls public static final String ACTION_ELEMENT_NAME = "action";
@@ -360,7 +361,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
private static void assertActionIsGroupOrStub(final AnAction action) {
- if (!(action instanceof ActionGroup || action instanceof ActionStub)) {
+ if (!(action instanceof ActionGroup || action instanceof ActionStub || action instanceof ChameleonAction)) {
LOG.error("Action : " + action + "; class: " + action.getClass());
}
}
@@ -520,11 +521,9 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
LOG.assertTrue(action.equals(stub));
AnAction anAction = convertStub(stub);
-
- addToMap(stub.getId(), anAction, stub.getPluginId(), stub.getProjectType() == null ? null : new ProjectType(stub.getProjectType()));
myAction2Id.put(anAction, stub.getId());
- return anAction;
+ return addToMap(stub.getId(), anAction, stub.getPluginId(), stub.getProjectType());
}
@Override
@@ -653,7 +652,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
else {
- registerAction(id, action, pluginId);
+ registerAction(id, action, pluginId, element.getAttributeValue(PROJECT_TYPE));
}
}
}
@@ -991,8 +990,12 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
@Override
public void registerAction(@NotNull String actionId, @NotNull AnAction action, @Nullable PluginId pluginId) {
+ registerAction(actionId, action, pluginId, null);
+ }
+
+ public void registerAction(@NotNull String actionId, @NotNull AnAction action, @Nullable PluginId pluginId, @Nullable String projectType) {
synchronized (myLock) {
- if (!addToMap(actionId, action, pluginId, null)) return;
+ if (addToMap(actionId, action, pluginId, projectType) == null) return;
if (myAction2Id.containsKey(action)) {
reportActionError(pluginId, "action was already registered for another ID. ID is " + myAction2Id.get(action) +
getPluginInfo(pluginId));
@@ -1012,31 +1015,42 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- public boolean addToMap(String actionId, AnAction action, PluginId pluginId, ProjectType projectType) {
- if (myId2Action.containsKey(actionId)) {
- // make sure id+projectType is unique
- AnAction o = myId2Action.get(actionId);
- ChameleonAction chameleonAction;
- if (o instanceof ChameleonAction) {
- chameleonAction = (ChameleonAction)o;
- }
- else {
- chameleonAction = new ChameleonAction(o, projectType);
- myId2Action.put(actionId, chameleonAction);
- }
- AnAction old = chameleonAction.addAction(action, projectType);
- if (old != null) {
- reportActionError(pluginId,
- "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action +
- "; Registered action is " +
- myId2Action.get(actionId) + getPluginInfo(pluginId));
- return false;
- }
+ private AnAction addToMap(String actionId, AnAction action, PluginId pluginId, String projectType) {
+ if (projectType != null || myId2Action.containsKey(actionId)) {
+ return registerChameleon(actionId, action, pluginId, projectType);
}
else {
myId2Action.put(actionId, action);
+ return action;
}
- return true;
+ }
+
+ private AnAction registerChameleon(String actionId, AnAction action, PluginId pluginId, String projectType) {
+ ProjectType type = projectType == null ? null : new ProjectType(projectType);
+ // make sure id+projectType is unique
+ AnAction o = myId2Action.get(actionId);
+ ChameleonAction chameleonAction;
+ if (o == null) {
+ chameleonAction = new ChameleonAction(action, type);
+ myId2Action.put(actionId, chameleonAction);
+ return chameleonAction;
+ }
+ if (o instanceof ChameleonAction) {
+ chameleonAction = (ChameleonAction)o;
+ }
+ else {
+ chameleonAction = new ChameleonAction(o, type);
+ myId2Action.put(actionId, chameleonAction);
+ }
+ AnAction old = chameleonAction.addAction(action, type);
+ if (old != null) {
+ reportActionError(pluginId,
+ "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action +
+ "; Registered action is " +
+ myId2Action.get(actionId) + getPluginInfo(pluginId));
+ return null;
+ }
+ return chameleonAction;
}
@Override
@@ -1053,7 +1067,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
return;
}
}
- AnAction oldValue = (AnAction)myId2Action.remove(actionId);
+ AnAction oldValue = myId2Action.remove(actionId);
myAction2Id.remove(oldValue);
myId2Index.remove(actionId);
for (PluginId pluginName : myPlugin2Id.keySet()) {
@@ -1251,7 +1265,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
- public void preloadActions() {
+ public Future<?> preloadActions() {
if (myPreloadActionsRunnable == null) {
myPreloadActionsRunnable = new Runnable() {
@Override
@@ -1262,8 +1276,9 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
}
}
};
- ApplicationManager.getApplication().executeOnPooledThread(myPreloadActionsRunnable);
+ return ApplicationManager.getApplication().executeOnPooledThread(myPreloadActionsRunnable);
}
+ return null;
}
private void doPreloadActions() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java
index 4b46dc191c0c..f4e92f7eae02 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ChameleonAction.java
@@ -15,14 +15,13 @@
*/
package com.intellij.openapi.actionSystem.impl;
-import com.intellij.openapi.actionSystem.ActionStub;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectType;
import com.intellij.openapi.project.ProjectTypeService;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.util.HashMap;
import java.util.Map;
@@ -36,6 +35,7 @@ public class ChameleonAction extends AnAction {
public ChameleonAction(@NotNull AnAction first, ProjectType projectType) {
addAction(first, projectType);
+ copyFrom(myActions.values().iterator().next());
}
public AnAction addAction(AnAction action, ProjectType projectType) {
@@ -48,21 +48,35 @@ public class ChameleonAction extends AnAction {
}
@Override
- public void actionPerformed(AnActionEvent e) {
- getAction(e).actionPerformed(e);
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ AnAction action = getAction(e);
+ assert action != null;
+ action.actionPerformed(e);
}
@Override
- public void update(AnActionEvent e) {
- super.update(e);
+ public void update(@NotNull AnActionEvent e) {
+ AnAction action = getAction(e);
+ if (action != null) {
+ e.getPresentation().setVisible(true);
+ action.update(e);
+ }
+ else {
+ e.getPresentation().setVisible(false);
+ }
}
+ @Nullable
private AnAction getAction(AnActionEvent e) {
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
ProjectType projectType = ProjectTypeService.getProjectType(project);
AnAction action = myActions.get(projectType);
if (action == null) action = myActions.get(null);
- if (action == null) action = myActions.values().iterator().next();
return action;
}
+
+ @TestOnly
+ public Map<ProjectType, AnAction> getActions() {
+ return myActions;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java
index 85c0555f9bc6..9af1d30c28bf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
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.IdeFocusManager;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
@@ -164,7 +165,7 @@ public class Utils{
}
}
else if (child instanceof Separator) {
- if (!list.isEmpty() && !(list.get(list.size() - 1) instanceof Separator)) {
+ if (!StringUtil.isEmpty(((Separator)child).getText()) || (!list.isEmpty() && !(list.get(list.size() - 1) instanceof Separator))) {
list.add(child);
}
}
@@ -284,8 +285,10 @@ public class Utils{
for (int i = 0, size = list.size(); i < size; i++) {
final AnAction action = list.get(i);
if (action instanceof Separator) {
- if (i > 0 && i < size - 1) {
+ final String text = ((Separator)action).getText();
+ if (!StringUtil.isEmpty(text) || (i > 0 && i < size - 1)) {
component.add(new JPopupMenu.Separator() {
+ private final JMenuItem myMenu = !StringUtil.isEmpty(text) ? new JMenuItem(text) : null;
@Override
public Insets getInsets() {
final Insets insets = super.getInsets();
@@ -296,12 +299,29 @@ public class Utils{
}
@Override
+ public void doLayout() {
+ super.doLayout();
+ if (myMenu != null) {
+ myMenu.setBounds(getBounds());
+ }
+ }
+
+ @Override
protected void paintComponent(Graphics g) {
if (UIUtil.isUnderWindowsClassicLookAndFeel() || UIUtil.isUnderDarcula() || UIUtil.isUnderWindowsLookAndFeel()) {
g.setColor(component.getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
- super.paintComponent(g);
+ if (myMenu != null) {
+ myMenu.paint(g);
+ } else {
+ super.paintComponent(g);
+ }
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return myMenu != null ? myMenu.getPreferredSize() : super.getPreferredSize();
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/PluginPathManager.java b/platform/platform-impl/src/com/intellij/openapi/application/PluginPathManager.java
index 1ab050053e28..9bad9d2d3774 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/PluginPathManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/PluginPathManager.java
@@ -16,8 +16,10 @@
package com.intellij.openapi.application;
import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
+import java.io.FileFilter;
import java.util.*;
/**
@@ -32,26 +34,38 @@ public class PluginPathManager {
private static List<File> findSubrepos() {
List<File> result = new ArrayList<File>();
- File[] subdirs = new File(PathManager.getHomePath()).listFiles();
- if (subdirs == null) return result;
- Arrays.sort(subdirs, new Comparator<File>() {
+ File[] gitRoots = getSortedGitRoots(new File(PathManager.getHomePath()));
+ for (File subdir : gitRoots) {
+ File pluginsDir = new File(subdir, "plugins");
+ if (pluginsDir.exists()) {
+ result.add(pluginsDir);
+ }
+ else {
+ result.add(subdir);
+ }
+ result.addAll(Arrays.asList(getSortedGitRoots(subdir)));
+ }
+ return result;
+ }
+
+ @NotNull
+ private static File[] getSortedGitRoots(@NotNull File dir) {
+ File[] gitRoots = dir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File child) {
+ return child.isDirectory() && new File(child, ".git").exists();
+ }
+ });
+ if (gitRoots == null) {
+ return new File[0];
+ }
+ Arrays.sort(gitRoots, new Comparator<File>() {
@Override
public int compare(File file, File file2) {
return FileUtil.compareFiles(file, file2);
}
});
- for (File subdir : subdirs) {
- if (new File(subdir, ".git").exists()) {
- File pluginsDir = new File(subdir, "plugins");
- if (pluginsDir.exists()) {
- result.add(pluginsDir);
- }
- else {
- result.add(subdir);
- }
- }
- }
- return result;
+ return gitRoots;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index e3a36a2e59ab..a8eca00b505e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
@@ -531,10 +531,10 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
@Override
public void load(@Nullable String optionsPath) throws IOException {
- load(PathManager.getConfigPath(), optionsPath);
+ load(PathManager.getConfigPath(), optionsPath == null ? PathManager.getOptionsPath() : optionsPath);
}
- public void load(@NotNull String configPath, @Nullable String optionsPath) throws IOException {
+ public void load(@NotNull String configPath, @NotNull String optionsPath) throws IOException {
getStateStore().setOptionsPath(optionsPath);
getStateStore().setConfigPath(configPath);
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
index a00533d3244b..bf03cb11f1d6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java
@@ -36,7 +36,6 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
private static final String XML_EXTENSION = ".xml";
private static final String DEFAULT_STORAGE_SPEC = StoragePathMacros.APP_CONFIG + "/" + PathManager.DEFAULT_OPTIONS_FILE_NAME + XML_EXTENSION;
- private static final String OPTIONS_MACRO = "OPTIONS";
private static final String ROOT_ELEMENT_NAME = "application";
private final ApplicationImpl myApplication;
@@ -93,14 +92,13 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
}
@Override
- public void setOptionsPath(final String path) {
- myStateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.APP_CONFIG), path);
- myStateStorageManager.addMacro(OPTIONS_MACRO, path);
+ public void setOptionsPath(@NotNull String path) {
+ myStateStorageManager.addMacro(StoragePathMacros.APP_CONFIG, path);
}
@Override
public void setConfigPath(@NotNull final String configPath) {
- myStateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.ROOT_CONFIG), configPath);
+ myStateStorageManager.addMacro(StoragePathMacros.ROOT_CONFIG, configPath);
myConfigPath = configPath;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
index 25dd8a05cab3..dc07fee151e2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java
@@ -59,8 +59,8 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
}
@Override
- public void load(@NotNull final Element rootElement) throws IOException {
- super.load(rootElement);
+ public void load(@NotNull Element rootElement, @Nullable PathMacroSubstitutor pathMacroSubstitutor, boolean intern) {
+ super.load(rootElement, pathMacroSubstitutor, intern);
final String v = rootElement.getAttributeValue(VERSION_OPTION);
if (v != null) {
@@ -74,7 +74,11 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
@Override
@NotNull
protected Element save() {
- final Element root = super.save();
+ Element root = super.save();
+ if (root == null) {
+ root = new Element(myRootElementName);
+ }
+
root.setAttribute(VERSION_OPTION, Integer.toString(myVersion));
return root;
}
@@ -113,7 +117,7 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
}
public BaseStorageData getMainStorageData() throws StateStorageException {
- return (BaseStorageData) getMainStorage().getStorageData(false);
+ return (BaseStorageData)getMainStorage().getStorageData();
}
@Nullable
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
index fc2017b57a4a..ed63bf12d4c4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
@@ -29,12 +29,12 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ReflectionUtil;
-import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;
@@ -46,12 +46,6 @@ public abstract class ComponentStoreImpl implements IComponentStore {
private final List<SettingsSavingComponent> mySettingsSavingComponents = Collections.synchronizedList(new ArrayList<SettingsSavingComponent>());
@Nullable private SaveSessionImpl mySession;
- @Deprecated
- @Nullable
- private StateStorage getStateStorage(@NotNull final Storage storageSpec) throws StateStorageException {
- return getStateStorageManager().getStateStorage(storageSpec);
- }
-
@Nullable
protected abstract StateStorage getDefaultsStorage();
@@ -255,9 +249,10 @@ public abstract class ComponentStoreImpl implements IComponentStore {
Storage[] storageSpecs = getComponentStorageSpecs(component, StateStorageOperation.READ);
for (Storage storageSpec : storageSpecs) {
- StateStorage stateStorage = getStateStorage(storageSpec);
- if (stateStorage == null || !stateStorage.hasState(component, name, stateClass, reloadData)) continue;
- state = stateStorage.getState(component, name, stateClass, state);
+ StateStorage stateStorage = getStateStorageManager().getStateStorage(storageSpec);
+ if (stateStorage != null && stateStorage.hasState(component, name, stateClass, reloadData)) {
+ state = stateStorage.getState(component, name, stateClass, state);
+ }
}
if (state != null) {
@@ -320,17 +315,15 @@ public abstract class ComponentStoreImpl implements IComponentStore {
}
assert storages.length > 0;
- final Class<StorageAnnotationsDefaultValues.NullStateStorageChooser> defaultClass =
- StorageAnnotationsDefaultValues.NullStateStorageChooser.class;
-
final Class<? extends StateStorageChooser> storageChooserClass = stateSpec.storageChooser();
- final StateStorageChooser<PersistentStateComponent<?>> defaultStateStorageChooser = getDefaultStateStorageChooser();
- assert storageChooserClass != defaultClass || defaultStateStorageChooser != null : "State chooser not specified for: " +
- persistentStateComponent.getClass();
-
- if (storageChooserClass == defaultClass) {
+ if (storageChooserClass == StateStorageChooser.class) {
+ StateStorageChooser<PersistentStateComponent<?>> defaultStateStorageChooser = getDefaultStateStorageChooser();
+ assert defaultStateStorageChooser != null : "State chooser not specified for: " + persistentStateComponent.getClass();
return defaultStateStorageChooser.selectStorages(storages, persistentStateComponent, operation);
}
+ else if (storageChooserClass == LastStorageChooserForWrite.class) {
+ return LastStorageChooserForWrite.INSTANCE.selectStorages(storages, persistentStateComponent, operation);
+ }
else {
try {
@SuppressWarnings("unchecked")
@@ -361,7 +354,7 @@ public abstract class ComponentStoreImpl implements IComponentStore {
@NotNull
@Override
- public List<IFile> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException {
+ public List<File> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException {
try {
return myStorageManagerSaveSession.getAllStorageFilesToSave();
}
@@ -426,12 +419,10 @@ public abstract class ComponentStoreImpl implements IComponentStore {
protected void commit() throws StateStorageException {
final StateStorageManager storageManager = getStateStorageManager();
-
final StateStorageManager.ExternalizationSession session = storageManager.startExternalization();
String[] names = ArrayUtil.toStringArray(myComponents.keySet());
Arrays.sort(names);
-
for (String name : names) {
Object component = myComponents.get(name);
if (component instanceof PersistentStateComponent) {
@@ -452,10 +443,9 @@ public abstract class ComponentStoreImpl implements IComponentStore {
@NotNull
@Override
- public List<IFile> getAllStorageFiles(final boolean includingSubStructures) {
+ public List<File> getAllStorageFiles(final boolean includingSubStructures) {
return myStorageManagerSaveSession.getAllStorageFiles();
}
-
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
index 51cc717726f3..aacdb58aeeec 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
@@ -18,9 +18,9 @@ package com.intellij.openapi.components.impl.stores;
import com.intellij.openapi.components.StateStorage;
import com.intellij.openapi.components.StateStorageException;
import com.intellij.util.SmartList;
-import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
+import java.io.File;
import java.util.List;
import java.util.Map;
@@ -36,8 +36,8 @@ public class CompoundSaveSession {
}
}
- public List<IFile> getAllStorageFilesToSave() throws StateStorageException {
- List<IFile> result = new SmartList<IFile>();
+ public List<File> getAllStorageFilesToSave() throws StateStorageException {
+ List<File> result = new SmartList<File>();
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
result.addAll(saveSession.getStorageFilesToSave());
}
@@ -70,8 +70,8 @@ public class CompoundSaveSession {
return mySaveSessions.get(storage);
}
- public List<IFile> getAllStorageFiles() {
- List<IFile> result = new SmartList<IFile>();
+ public List<File> getAllStorageFiles() {
+ List<File> result = new SmartList<File>();
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
result.addAll(saveSession.getAllStorageFiles());
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
index 6f0c3b8122cf..fad17c8d2889 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java
@@ -21,13 +21,12 @@ import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.project.impl.ProjectManagerImpl;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.io.fs.IFile;
-import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
@@ -40,10 +39,10 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
private final ProjectManagerImpl myProjectManager;
@NonNls private static final String ROOT_TAG_NAME = "defaultProject";
- public DefaultProjectStoreImpl(final ProjectImpl project, final ProjectManagerImpl projectManager) {
+ public DefaultProjectStoreImpl(@NotNull ProjectImpl project, final ProjectManagerImpl projectManager) {
super(project);
- myProjectManager = projectManager;
+ myProjectManager = projectManager;
myElement = projectManager.getDefaultProjectRootElement();
}
@@ -53,29 +52,28 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
return element != null ? element.clone() : null;
}
-
@NotNull
@Override
protected StateStorageManager createStateStorageManager() {
- Document _d = null;
+ Element _d = null;
if (myElement != null) {
myElement.detach();
- _d = new Document(myElement);
+ _d = myElement;
}
final ComponentManager componentManager = getComponentManager();
final PathMacroManager pathMacroManager = PathMacroManager.getInstance(componentManager);
- final Document document = _d;
+ final Element element = _d;
- final XmlElementStorage storage = new XmlElementStorage(pathMacroManager.createTrackingSubstitutor(), componentManager,
- ROOT_TAG_NAME, null, "", ComponentRoamingManager.getInstance(),
+ final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, pathMacroManager.createTrackingSubstitutor(), componentManager,
+ ROOT_TAG_NAME, null,
ComponentVersionProvider.EMPTY) {
@Override
@Nullable
- protected Document loadDocument() throws StateStorageException {
- return document;
+ protected Element loadLocalData() {
+ return element;
}
@Override
@@ -96,26 +94,28 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
@Override
protected void doSave() throws StateStorageException {
- myProjectManager.setDefaultProjectRootElement(getDocumentToSave().getRootElement());
+ Element element = getElementToSave();
+ myProjectManager.setDefaultProjectRootElement(element == null ? null : element);
}
@NotNull
@Override
- public Collection<IFile> getStorageFilesToSave() throws StateStorageException {
+ public Collection<File> getStorageFilesToSave() throws StateStorageException {
return Collections.emptyList();
}
@NotNull
@Override
- public List<IFile> getAllStorageFiles() {
+ public List<File> getAllStorageFiles() {
return Collections.emptyList();
}
}
};
+ //noinspection deprecation
return new StateStorageManager() {
@Override
- public void addMacro(String macro, String expansion) {
+ public void addMacro(@NotNull String macro, @NotNull String expansion) {
throw new UnsupportedOperationException("Method addMacro not implemented in " + getClass());
}
@@ -131,6 +131,12 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
return storage;
}
+ @Nullable
+ @Override
+ public StateStorage getStateStorage(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
+ return storage;
+ }
+
@Override
@Nullable
public StateStorage getFileStateStorage(@NotNull String fileSpec) {
@@ -158,6 +164,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
storage.finishSave(((MySaveSession)saveSession).saveSession);
}
+ @NotNull
@Override
public String expandMacros(@NotNull String file) {
throw new UnsupportedOperationException("Method expandMacros not implemented in " + getClass());
@@ -186,6 +193,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
throw new UnsupportedOperationException("Method getStreamProviders not implemented in " + getClass());
}
+ @NotNull
@Override
public Collection<String> getStorageFileNames() {
throw new UnsupportedOperationException("Method getStorageFileNames not implemented in " + getClass());
@@ -238,13 +246,13 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
@NotNull
@Override
- public List<IFile> getAllStorageFilesToSave() throws StateStorageException {
+ public List<File> getAllStorageFilesToSave() throws StateStorageException {
return Collections.emptyList();
}
@NotNull
@Override
- public List<IFile> getAllStorageFiles() {
+ public List<File> getAllStorageFiles() {
return Collections.emptyList();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java
index b62db63b73c2..9415aee49b09 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultsStateStorage.java
@@ -65,12 +65,12 @@ class DefaultsStateStorage implements StateStorage {
}
@Nullable
- public <T> T getState(final Object component, final String componentName, final Class<T> stateClass, @Nullable final T mergeInto) throws
+ public <T> T getState(final Object component, @NotNull final String componentName, final Class<T> stateClass, @Nullable final T mergeInto) throws
StateStorageException {
return DefaultStateSerializer.deserializeState(getState(component, componentName), stateClass, mergeInto);
}
- public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
+ public boolean hasState(final Object component, @NotNull final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
final URL url = DecodeDefaultsUtil.getDefaults(component, componentName);
return url != null;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java
index cda453be5cd2..912c239cffcb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java
@@ -26,7 +26,8 @@ import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.tracker.VirtualFileTracker;
-import com.intellij.util.io.fs.IFile;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.messages.MessageBus;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -37,16 +38,13 @@ import java.io.File;
import java.io.IOException;
import java.util.*;
-import static com.intellij.util.io.fs.FileSystem.FILE_SYSTEM;
-
//todo: support missing plugins
//todo: support storage data
public class DirectoryBasedStorage implements StateStorage, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.DirectoryBasedStorage");
- private static final IFile[] EMPTY_FILES = new IFile[0];
private final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
- private final IFile myDir;
+ private final File myDir;
private final StateSplitter mySplitter;
private final FileTypeManager myFileTypeManager;
@@ -59,7 +57,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@NotNull Disposable parentDisposable,
@NotNull PicoContainer picoContainer) {
myPathMacroSubstitutor = pathMacroSubstitutor;
- myDir = FILE_SYSTEM.createFile(dir);
+ myDir = new File(dir);
mySplitter = splitter;
Disposer.register(parentDisposable, this);
@@ -96,7 +94,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@Override
@Nullable
- public <T> T getState(final Object component, final String componentName, Class<T> stateClass, @Nullable T mergeInto)
+ public <T> T getState(final Object component, @NotNull final String componentName, Class<T> stateClass, @Nullable T mergeInto)
throws StateStorageException {
if (myStorageData == null) myStorageData = loadState();
@@ -116,7 +114,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@Override
- public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
+ public boolean hasState(final Object component, @NotNull String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
if (!myDir.exists()) return false;
if (reloadData) myStorageData = null;
return true;
@@ -180,32 +178,28 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@Override
public void save() throws StateStorageException {
assert mySession == this;
- final Set<String> currentNames = new HashSet<String>();
-
- IFile[] children = myDir.exists() ? myDir.listFiles() : EMPTY_FILES;
- for (IFile child : children) {
- final String fileName = child.getName();
- if (!myFileTypeManager.isFileIgnored(fileName) && StringUtil.endsWithIgnoreCase(fileName, ".xml")) {
- currentNames.add(fileName);
+ final Set<String> currentNames = new SmartHashSet<String>();
+ File[] children = myDir.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ final String fileName = child.getName();
+ if (!myFileTypeManager.isFileIgnored(fileName) && StringUtil.endsWithIgnoreCase(fileName, ".xml")) {
+ currentNames.add(fileName);
+ }
}
}
myStorageData.process(new DirectoryStorageData.StorageDataProcessor() {
@Override
- public void process(final String componentName, final IFile file, final Element element) {
+ public void process(final String componentName, final File file, final Element element) {
currentNames.remove(file.getName());
if (myPathMacroSubstitutor != null) {
myPathMacroSubstitutor.collapsePaths(element);
}
- if (file.getTimeStamp() <= myStorageData.getLastTimeStamp()) {
- if (!myDir.exists()) {
- myDir.createParentDirs();
- myDir.mkDir();
- }
-
- StorageUtil.save(file, element, MySaveSession.this);
+ if (file.lastModified() <= myStorageData.getLastTimeStamp()) {
+ StorageUtil.save(file, element, MySaveSession.this, false, null);
myStorageData.updateLastTimestamp(file);
}
}
@@ -217,15 +211,14 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
public void run() {
if (myDir.exists()) {
for (String name : currentNames) {
- IFile child = myDir.getChild(name);
-
- if (child.getTimeStamp() > myStorageData.getLastTimeStamp()) {
+ File child = new File(myDir, name);
+ if (child.lastModified() > myStorageData.getLastTimeStamp()) {
// do not touch new files during VC update (which aren't read yet)
// now got an opposite problem: file is recreated if was removed by VC during update.
return;
}
- final VirtualFile virtualFile = StorageUtil.getVirtualFile(child);
+ final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(child);
if (virtualFile != null) {
try {
LOG.debug("Removing configuration file: " + virtualFile.getPresentableUrl());
@@ -272,23 +265,26 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@Override
@NotNull
- public Collection<IFile> getStorageFilesToSave() throws StateStorageException {
+ public Collection<File> getStorageFilesToSave() throws StateStorageException {
assert mySession == this;
if (!myDir.exists()) return getAllStorageFiles();
assert myDir.isDirectory() : myDir.getPath();
- final List<IFile> filesToSave = new ArrayList<IFile>();
-
- IFile[] children = myDir.listFiles();
- final Set<String> currentChildNames = new HashSet<String>();
- for (IFile child : children) {
- if (!myFileTypeManager.isFileIgnored(child.getName())) currentChildNames.add(child.getName());
+ final List<File> filesToSave = new ArrayList<File>();
+ final Set<String> currentChildNames = new SmartHashSet<String>();
+ File[] children = myDir.listFiles();
+ if (children != null) {
+ for (File child : children) {
+ if (!myFileTypeManager.isFileIgnored(child.getName())) {
+ currentChildNames.add(child.getName());
+ }
+ }
}
myStorageData.process(new DirectoryStorageData.StorageDataProcessor() {
@Override
- public void process(final String componentName, final IFile file, final Element element) {
+ public void process(final String componentName, final File file, final Element element) {
if (currentChildNames.contains(file.getName())) {
currentChildNames.remove(file.getName());
@@ -301,13 +297,11 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
filesToSave.add(file);
}
}
-
}
});
for (String childName : currentChildNames) {
- final IFile child = myDir.getChild(childName);
- filesToSave.add(child);
+ filesToSave.add(new File(myDir, childName));
}
return filesToSave;
@@ -315,8 +309,8 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
@Override
@NotNull
- public List<IFile> getAllStorageFiles() {
- return new ArrayList<IFile>(myStorageData.getAllStorageFiles().keySet());
+ public List<File> getAllStorageFiles() {
+ return new SmartList<File>(myStorageData.getAllStorageFiles().keySet());
}
}
@@ -328,24 +322,25 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
}
@Override
- public void setState(@NotNull final Object component, final String componentName, @NotNull final Object state, final Storage storageSpec)
- throws StateStorageException {
+ public void setState(@NotNull final Object component, final String componentName, @NotNull final Object state, final Storage storageSpec) {
assert mySession == this;
setState(componentName, state, storageSpec);
}
- private void setState(final String componentName, @NotNull Object state, final Storage storageSpec) throws StateStorageException {
+ private void setState(final String componentName, @NotNull Object state, final Storage storageSpec) {
try {
final Element element = DefaultStateSerializer.serializeState(state, storageSpec);
- for (Pair<Element, String> pair : mySplitter.splitState(element)) {
- Element e = pair.first;
- String name = pair.second;
+ if (element != null) {
+ for (Pair<Element, String> pair : mySplitter.splitState(element)) {
+ Element e = pair.first;
+ String name = pair.second;
- Element statePart = new Element(StorageData.COMPONENT);
- statePart.setAttribute(StorageData.NAME, componentName);
- statePart.addContent(e.detach());
+ Element statePart = new Element(StorageData.COMPONENT);
+ statePart.setAttribute(StorageData.NAME, componentName);
+ statePart.addContent(e.detach());
- myStorageData.put(componentName, myDir.getChild(name), statePart, false);
+ myStorageData.put(componentName, new File(myDir, name), statePart, false);
+ }
}
}
catch (WriteExternalException e) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
index 923072d4fb1d..54fd9d65cb92 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
@@ -22,19 +22,14 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.components.StateStorageException;
-import com.intellij.openapi.components.StoragePathMacros;
-import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
+import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.tracker.VirtualFileTracker;
-import com.intellij.util.io.fs.FileSystem;
-import com.intellij.util.io.fs.IFile;
import com.intellij.util.messages.MessageBus;
-import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
@@ -44,46 +39,40 @@ import org.picocontainer.PicoContainer;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class FileBasedStorage extends XmlElementStorage {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.FileBasedStorage");
+ private static final Logger LOG = Logger.getInstance(FileBasedStorage.class);
private static boolean ourConfigDirectoryRefreshed = false;
private final String myFilePath;
- private final IFile myFile;
- private final String myRootElementName;
+ private final File myFile;
private volatile VirtualFile myCachedVirtualFile;
- public FileBasedStorage(@Nullable TrackingPathMacroSubstitutor pathMacroManager,
- StreamProvider streamProvider,
- String filePath,
- String fileSpec,
- String rootElementName,
+ public FileBasedStorage(@NotNull String filePath,
+ @NotNull String fileSpec,
+ @Nullable RoamingType roamingType,
+ @Nullable TrackingPathMacroSubstitutor pathMacroManager,
+ @NotNull String rootElementName,
@NotNull Disposable parentDisposable,
PicoContainer picoContainer,
- ComponentRoamingManager componentRoamingManager,
+ @Nullable StreamProvider streamProvider,
ComponentVersionProvider componentVersionProvider) {
- super(pathMacroManager, parentDisposable, rootElementName, streamProvider, fileSpec, componentRoamingManager, componentVersionProvider);
+ super(fileSpec, roamingType, pathMacroManager, parentDisposable, rootElementName, streamProvider, componentVersionProvider);
refreshConfigDirectoryOnce();
- myRootElementName = rootElementName;
myFilePath = filePath;
- myFile = FileSystem.FILE_SYSTEM.createFile(myFilePath);
+ myFile = new File(filePath);
VirtualFileTracker virtualFileTracker = ServiceManager.getService(VirtualFileTracker.class);
MessageBus messageBus = (MessageBus)picoContainer.getComponentInstanceOfType(MessageBus.class);
if (virtualFileTracker != null && messageBus != null) {
- final String path = myFile.getAbsolutePath();
- final String fileUrl = LocalFileSystem.PROTOCOL_PREFIX + path.replace(File.separatorChar, '/');
-
final Listener listener = messageBus.syncPublisher(STORAGE_TOPIC);
- virtualFileTracker.addTracker(fileUrl, new VirtualFileAdapter() {
+ virtualFileTracker.addTracker(LocalFileSystem.PROTOCOL_PREFIX + myFile.getAbsolutePath().replace(File.separatorChar, '/'), new VirtualFileAdapter() {
@Override
public void fileMoved(@NotNull VirtualFileMoveEvent event) {
myCachedVirtualFile = null;
@@ -95,6 +84,11 @@ public class FileBasedStorage extends XmlElementStorage {
}
@Override
+ public void fileCreated(@NotNull VirtualFileEvent event) {
+ myCachedVirtualFile = event.getFile();
+ }
+
+ @Override
public void contentsChanged(@NotNull final VirtualFileEvent event) {
if (!isDisposed()) {
listener.storageFileChanged(event, FileBasedStorage.this);
@@ -130,13 +124,6 @@ public class FileBasedStorage extends XmlElementStorage {
return new FileSaveSession(externalizationSession);
}
- public void resetProviderCache() {
- myProviderUpToDateHash = -1;
- if (myRemoteVersionProvider != null) {
- myRemoteVersionProvider.myProviderVersions = null;
- }
- }
-
private class FileSaveSession extends MySaveSession {
protected FileSaveSession(MyExternalizationSession externalizationSession) {
super(externalizationSession);
@@ -145,9 +132,11 @@ public class FileBasedStorage extends XmlElementStorage {
@Override
protected boolean physicalContentNeedsSave() {
VirtualFile file = getVirtualFile();
- if (file == null || !file.exists())
+ if (file == null || !file.exists()) {
return !myStorageData.isEmpty();
- return !StorageUtil.contentEquals(getDocumentToSave(), file);
+ }
+ Element element = getElementToSave();
+ return element == null || !StorageUtil.contentEquals(element, file);
}
@Override
@@ -169,14 +158,13 @@ public class FileBasedStorage extends XmlElementStorage {
}
LOG.assertTrue(myFile != null);
- myCachedVirtualFile = StorageUtil.save(myFile, getDocumentToSave(), this);
+ myCachedVirtualFile = StorageUtil.save(myFile, getElementToSave(), this, true, myCachedVirtualFile);
}
@NotNull
@Override
- public Collection<IFile> getStorageFilesToSave() throws StateStorageException {
- boolean needsSave = needsSave();
- if (needsSave) {
+ public Collection<File> getStorageFilesToSave() {
+ if (needsSave()) {
if (LOG.isDebugEnabled()) {
LOG.info("File " + myFileSpec + " needs save; hash=" + myUpToDateHash + "; currentHash=" + calcHash() + "; " +
"content needs save=" + physicalContentNeedsSave());
@@ -190,21 +178,17 @@ public class FileBasedStorage extends XmlElementStorage {
@NotNull
@Override
- public List<IFile> getAllStorageFiles() {
+ public List<File> getAllStorageFiles() {
return Collections.singletonList(myFile);
}
}
@Override
- protected void loadState(final StorageData result, final Element element) throws StateStorageException {
- ((FileStorageData)result).myFilePath = myFile.getAbsolutePath();
- super.loadState(result, element);
- }
-
- @Override
@NotNull
protected StorageData createStorageData() {
- return new FileStorageData(myRootElementName);
+ FileStorageData data = new FileStorageData(myRootElementName);
+ data.myFilePath = myFilePath;
+ return data;
}
public static class FileStorageData extends StorageData {
@@ -234,18 +218,24 @@ public class FileBasedStorage extends XmlElementStorage {
public VirtualFile getVirtualFile() {
VirtualFile virtualFile = myCachedVirtualFile;
if (virtualFile == null) {
- myCachedVirtualFile = virtualFile = StorageUtil.getVirtualFile(myFile);
+ myCachedVirtualFile = virtualFile = LocalFileSystem.getInstance().findFileByIoFile(myFile);
}
return virtualFile;
}
+ @NotNull
public File getFile() {
- return new File(myFile.getPath());
+ return myFile;
+ }
+
+ @NotNull
+ public String getFilePath() {
+ return myFilePath;
}
@Override
@Nullable
- protected Document loadDocument() throws StateStorageException {
+ protected Element loadLocalData() {
myBlockSavingTheContent = false;
try {
VirtualFile file = getVirtualFile();
@@ -256,7 +246,7 @@ public class FileBasedStorage extends XmlElementStorage {
if (file.getLength() == 0) {
return processReadException(null);
}
- return loadDocumentImpl(file);
+ return StorageData.load(file);
}
catch (final JDOMException e) {
return processReadException(e);
@@ -267,7 +257,7 @@ public class FileBasedStorage extends XmlElementStorage {
}
@Nullable
- private Document processReadException(@Nullable final Exception e) {
+ private Element processReadException(@Nullable final Exception e) {
boolean contentTruncated = e == null;
myBlockSavingTheContent = isProjectOrModuleOrWorkspaceFile() && !contentTruncated;
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
@@ -291,45 +281,27 @@ public class FileBasedStorage extends XmlElementStorage {
return isProjectOrModuleOrWorkspaceFile() && !contentTruncated ? "Please correct the file content" : "File content will be recreated";
}
- private static Document loadDocumentImpl(final VirtualFile file) throws IOException, JDOMException {
- InputStream stream = file.getInputStream();
- try {
- return JDOMUtil.loadDocument(stream);
- }
- finally {
- stream.close();
- }
- }
-
- public String getFileName() {
- return myFile.getName();
- }
-
- public String getFilePath() {
- return myFilePath;
- }
-
@Override
public void setDefaultState(final Element element) {
element.setName(myRootElementName);
super.setDefaultState(element);
}
- protected boolean physicalContentNeedsSave(final Document doc) {
- VirtualFile file = getVirtualFile();
- return file == null || !file.exists() || !StorageUtil.contentEquals(doc, file);
- }
-
@Nullable
public File updateFileExternallyFromStreamProviders() throws IOException {
- StorageData loadedData = loadData(true);
- Document document = getDocument(loadedData);
- if (physicalContentNeedsSave(document)) {
- File file = new File(myFile.getAbsolutePath());
- JDOMUtil.writeDocument(document, file, "\n");
- return file;
+ Element element = getElement(loadData(true));
+ if (element == null) {
+ FileUtil.delete(myFile);
+ return null;
}
- return null;
+ BufferExposingByteArrayOutputStream out = StorageUtil.newContentIfDiffers(element, getVirtualFile());
+ if (out == null) {
+ return null;
+ }
+
+ File file = new File(myFile.getAbsolutePath());
+ FileUtil.writeToFile(file, out.getInternalBuffer(), 0, out.size());
+ return file;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IApplicationStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IApplicationStore.java
index c669bd1f37be..0ebfae887771 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IApplicationStore.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IApplicationStore.java
@@ -15,18 +15,18 @@
*/
package com.intellij.openapi.components.impl.stores;
-import com.intellij.openapi.components.StateStorageException;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.components.StateStorage;
+import com.intellij.openapi.components.StateStorageException;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-import java.util.Set;
-import java.util.Collection;
import java.io.IOException;
+import java.util.Collection;
+import java.util.Set;
public interface IApplicationStore extends IComponentStore {
- void setOptionsPath(String path);
+ void setOptionsPath(@NotNull String path);
void setConfigPath(@NotNull String configPath);
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java
index 0427a8be15ab..93a65a2eb50b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java
@@ -19,10 +19,10 @@ import com.intellij.openapi.components.StateStorage;
import com.intellij.openapi.components.StateStorageException;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.io.fs.IFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
@@ -54,17 +54,19 @@ public interface IComponentStore {
interface SaveSession {
@NotNull
- List<IFile> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException;
+ List<File> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException;
+
@NotNull
SaveSession save() throws IOException;
+
void finishSave();
+
void reset();
@Nullable
- Set<String> analyzeExternalChanges(@NotNull Set<Pair<VirtualFile,StateStorage>> changedFiles);
+ Set<String> analyzeExternalChanges(@NotNull Set<Pair<VirtualFile, StateStorage>> changedFiles);
@NotNull
- List<IFile> getAllStorageFiles(final boolean includingSubStructures);
+ List<File> getAllStorageFiles(final boolean includingSubStructures);
}
-
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
index 2120030db2c1..ac7bf84f6b3e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/OldStreamProviderAdapter.java
@@ -12,6 +12,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+@SuppressWarnings("deprecation")
final class OldStreamProviderAdapter extends StreamProvider implements CurrentUserHolder {
final com.intellij.openapi.options.StreamProvider myProvider;
private final RoamingType myRoamingType;
@@ -32,9 +33,8 @@ final class OldStreamProviderAdapter extends StreamProvider implements CurrentUs
}
@Override
- public boolean saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException {
+ public void saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException {
myProvider.saveContent(fileSpec, new BufferExposingByteArrayInputStream(content, size), size, roamingType, async);
- return false;
}
@Nullable
@@ -65,4 +65,4 @@ final class OldStreamProviderAdapter extends StreamProvider implements CurrentUs
public String getCurrentUserName() {
return myProvider instanceof CurrentUserHolder ? ((CurrentUserHolder)myProvider).getCurrentUserName() : null;
}
-} \ No newline at end of file
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
index 0eed50a65131..c7b93afbe8d8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStateStorageManager.java
@@ -56,17 +56,12 @@ class ProjectStateStorageManager extends StateStorageManagerImpl {
assert config != null : "Couldn't find old storage for " + component.getClass().getName();
final boolean workspace = isWorkspace(config.options);
- String macro = StoragePathMacros.getMacroName(workspace ? StoragePathMacros.WORKSPACE_FILE : StoragePathMacros.PROJECT_FILE);
-
- String name = "$" + macro + "$";
-
- StateStorage storage = getFileStateStorage(name);
-
+ String fileSpec = workspace ? StoragePathMacros.WORKSPACE_FILE : StoragePathMacros.PROJECT_FILE;
+ StateStorage storage = getStateStorage(fileSpec, workspace ? RoamingType.DISABLED : RoamingType.PER_USER);
if (operation == StateStorageOperation.READ && storage != null && workspace && !storage.hasState(component, componentName, Element.class, false)) {
- name = StoragePathMacros.PROJECT_FILE;
+ fileSpec = StoragePathMacros.PROJECT_FILE;
}
-
- return name;
+ return fileSpec;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
index 6288c62ab9e5..01e2f9e036d0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
@@ -39,13 +39,14 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.OrderedSet;
-import com.intellij.util.io.fs.FileSystem;
-import com.intellij.util.io.fs.IFile;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.lang.annotation.Annotation;
@@ -55,23 +56,21 @@ import java.util.List;
import java.util.Set;
class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProjectStore {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.ProjectStoreImpl");
+ private static final Logger LOG = Logger.getInstance(ProjectStoreImpl.class);
@NonNls private static final String OLD_PROJECT_SUFFIX = "_old.";
@NonNls static final String OPTION_WORKSPACE = "workspace";
- @NonNls static final String DEFAULT_STATE_STORAGE = StoragePathMacros.PROJECT_FILE;
-
static final Storage DEFAULT_STORAGE_ANNOTATION = new MyStorage();
private static int originalVersion = -1;
protected ProjectImpl myProject;
private StorageScheme myScheme = StorageScheme.DEFAULT;
- private String myCachedLocation;
private String myPresentableUrl;
- ProjectStoreImpl(final ProjectImpl project) {
+ ProjectStoreImpl(@NotNull ProjectImpl project) {
super(project);
+
myProject = project;
}
@@ -169,15 +168,15 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
final File dirStore = file.isDirectory() ? new File(file, Project.DIRECTORY_STORE_FOLDER)
: new File(file.getParentFile(), Project.DIRECTORY_STORE_FOLDER);
- stateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.PROJECT_FILE), new File(dirStore, "misc.xml").getPath());
+ stateStorageManager.addMacro(StoragePathMacros.PROJECT_FILE, new File(dirStore, "misc.xml").getPath());
final File ws = new File(dirStore, "workspace.xml");
- stateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.WORKSPACE_FILE), ws.getPath());
+ stateStorageManager.addMacro(StoragePathMacros.WORKSPACE_FILE, ws.getPath());
if (!ws.exists() && !file.isDirectory()) {
useOldWsContent(filePath, ws);
}
- stateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.PROJECT_CONFIG_DIR), dirStore.getPath());
+ stateStorageManager.addMacro(StoragePathMacros.PROJECT_CONFIG_DIR, dirStore.getPath());
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
@@ -189,10 +188,10 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
else {
myScheme = StorageScheme.DEFAULT;
- stateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.PROJECT_FILE), filePath);
+ stateStorageManager.addMacro(StoragePathMacros.PROJECT_FILE, filePath);
final String workspacePath = composeWsPath(filePath);
- stateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.WORKSPACE_FILE), workspacePath);
+ stateStorageManager.addMacro(StoragePathMacros.WORKSPACE_FILE, workspacePath);
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
@@ -202,7 +201,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
}, ModalityState.defaultModalityState());
}
- myCachedLocation = null;
myPresentableUrl = null;
}
@@ -258,18 +256,26 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
final String path = getProjectFilePath();
if (!StringUtil.isEmptyOrSpaces(path)) {
- return myScheme == StorageScheme.DEFAULT ? new File(path).getParent() : new File(path).getParentFile().getParent();
+ return getBasePath(new File(path));
}
//we are not yet initialized completely ("open directory", etc)
- final StateStorage s = getStateStorageManager().getFileStateStorage(StoragePathMacros.PROJECT_FILE);
- if (!(s instanceof FileBasedStorage)) return null;
- final FileBasedStorage storage = (FileBasedStorage)s;
+ StateStorage storage = getStateStorageManager().getStateStorage(StoragePathMacros.PROJECT_FILE, RoamingType.PER_USER);
+ if (!(storage instanceof FileBasedStorage)) {
+ return null;
+ }
- final File file = storage.getFile();
- if (file == null) return null;
+ return getBasePath(((FileBasedStorage)storage).getFile());
+ }
- return myScheme == StorageScheme.DEFAULT ? file.getParent() : file.getParentFile().getParent();
+ private String getBasePath(@NotNull File file) {
+ if (myScheme == StorageScheme.DEFAULT) {
+ return file.getParent();
+ }
+ else {
+ File parentFile = file.getParentFile();
+ return parentFile == null ? null : parentFile.getParent();
+ }
}
@NotNull
@@ -302,7 +308,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
return baseDir.getName().replace(":", "");
}
else {
- String temp = getProjectFileName();
+ String temp = PathUtilRt.getFileName(((FileBasedStorage)getProjectFileStorage()).getFilePath());
FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(temp);
if (fileType instanceof ProjectFileType) {
temp = temp.substring(0, temp.length() - fileType.getDefaultExtension().length() - 1);
@@ -316,13 +322,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
}
@NotNull
- private String getProjectFileName() {
- final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(StoragePathMacros.PROJECT_FILE);
- assert storage != null;
- return storage.getFileName();
- }
-
- @NotNull
@Override
public StorageScheme getStorageScheme() {
return myScheme;
@@ -349,26 +348,28 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
@Override
public VirtualFile getProjectFile() {
- if (myProject.isDefault()) return null;
- final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(StoragePathMacros.PROJECT_FILE);
+ return myProject.isDefault() ? null : ((FileBasedStorage)getProjectFileStorage()).getVirtualFile();
+ }
+
+ @NotNull
+ private XmlElementStorage getProjectFileStorage() {
+ // XmlElementStorage if default project, otherwise FileBasedStorage
+ XmlElementStorage storage = (XmlElementStorage)getStateStorageManager().getStateStorage(StoragePathMacros.PROJECT_FILE, RoamingType.PER_USER);
assert storage != null;
- return storage.getVirtualFile();
+ return storage;
}
@Override
public VirtualFile getWorkspaceFile() {
if (myProject.isDefault()) return null;
- final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(StoragePathMacros.WORKSPACE_FILE);
+ final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getStateStorage(StoragePathMacros.WORKSPACE_FILE, RoamingType.DISABLED);
assert storage != null;
return storage.getVirtualFile();
}
@Override
public void loadProjectFromTemplate(@NotNull final ProjectImpl defaultProject) {
- final StateStorage stateStorage = getStateStorageManager().getFileStateStorage(DEFAULT_STATE_STORAGE);
-
- assert stateStorage instanceof XmlElementStorage;
- XmlElementStorage xmlElementStorage = (XmlElementStorage)stateStorage;
+ XmlElementStorage stateStorage = getProjectFileStorage();
defaultProject.save();
final IProjectStore projectStore = defaultProject.getStateStore();
@@ -376,24 +377,19 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
DefaultProjectStoreImpl defaultProjectStore = (DefaultProjectStoreImpl)projectStore;
final Element element = defaultProjectStore.getStateCopy();
if (element != null) {
- xmlElementStorage.setDefaultState(element);
+ stateStorage.setDefaultState(element);
}
}
@NotNull
@Override
public String getProjectFilePath() {
- if (myProject.isDefault()) return "";
- final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(StoragePathMacros.PROJECT_FILE);
- assert storage != null;
- return storage.getFilePath();
+ return myProject.isDefault() ? "" : ((FileBasedStorage)getProjectFileStorage()).getFilePath();
}
@Override
protected XmlElementStorage getMainStorage() {
- final XmlElementStorage storage = (XmlElementStorage)getStateStorageManager().getFileStateStorage(DEFAULT_STATE_STORAGE);
- assert storage != null;
- return storage;
+ return getProjectFileStorage();
}
@NotNull
@@ -402,7 +398,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
return new ProjectStateStorageManager(PathMacroManager.getInstance(getComponentManager()).createTrackingSubstitutor(), myProject);
}
-
static class ProjectStorageData extends BaseStorageData {
protected final Project myProject;
@@ -447,16 +442,16 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
}
@Override
- public void load(@NotNull final Element root) throws IOException {
- final String v = root.getAttributeValue(VERSION_OPTION);
+ public void load(@NotNull Element rootElement, @Nullable PathMacroSubstitutor pathMacroSubstitutor, boolean intern) {
+ final String v = rootElement.getAttributeValue(VERSION_OPTION);
//noinspection AssignmentToStaticFieldFromInstanceMethod
originalVersion = v != null ? Integer.parseInt(v) : 0;
if (originalVersion != ProjectManagerImpl.CURRENT_FORMAT_VERSION) {
- convert(root, originalVersion);
+ convert(rootElement, originalVersion);
}
- super.load(root);
+ super.load(rootElement, pathMacroSubstitutor, intern);
}
protected void convert(final Element root, final int originalVersion) {
@@ -479,19 +474,16 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
@NotNull
@Override
- public List<IFile> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException {
- List<IFile> result = new ArrayList<IFile>();
-
+ public List<File> getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException {
+ List<File> result = new SmartList<File>();
if (includingSubStructures) {
- collectSubfilesToSave(result);
+ collectSubFilesToSave(result);
}
-
result.addAll(super.getAllStorageFilesToSave(false));
-
return result;
}
- protected void collectSubfilesToSave(final List<IFile> result) throws IOException { }
+ protected void collectSubFilesToSave(final List<File> result) throws IOException { }
@NotNull
@Override
@@ -523,10 +515,10 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
return ApplicationManager.getApplication().runReadAction(new Computable<ReadonlyStatusHandler.OperationStatus>() {
@Override
public ReadonlyStatusHandler.OperationStatus compute() {
- final List<IFile> filesToSave;
+ final List<File> filesToSave;
try {
filesToSave = getAllStorageFilesToSave(true);
- final Iterator<IFile> iterator = filesToSave.iterator();
+ final Iterator<File> iterator = filesToSave.iterator();
while (iterator.hasNext()) {
if (!iterator.next().exists()) {
iterator.remove();
@@ -543,14 +535,12 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
if (myProject.isToSaveProjectName()) {
final VirtualFile baseDir = getProjectBaseDir();
if (baseDir != null && baseDir.isValid()) {
- filesToSave.add(FileSystem.FILE_SYSTEM
- .createFile(new File(new File(baseDir.getPath(), Project.DIRECTORY_STORE_FOLDER), ProjectImpl.NAME_FILE).getPath()));
+ filesToSave.add(new File(new File(baseDir.getPath(), Project.DIRECTORY_STORE_FOLDER), ProjectImpl.NAME_FILE));
}
}
- for (IFile file : filesToSave) {
+ for (File file : filesToSave) {
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
-
if (virtualFile != null) {
virtualFile.refresh(false, false);
if (virtualFile.isValid() && !virtualFile.isWritable()) {
@@ -670,7 +660,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
@Override
public String file() {
- return DEFAULT_STATE_STORAGE;
+ return StoragePathMacros.PROJECT_FILE;
}
@Override
@@ -679,15 +669,21 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
}
@Override
+ public RoamingType roamingType() {
+ return RoamingType.PER_USER;
+ }
+
+ @Override
public Class<? extends StateStorage> storageClass() {
- return StorageAnnotationsDefaultValues.NullStateStorage.class;
+ return StateStorage.class;
}
@Override
public Class<? extends StateSplitter> stateSplitter() {
- return StorageAnnotationsDefaultValues.NullStateSplitter.class;
+ return StateSplitter.class;
}
+ @NotNull
@Override
public Class<? extends Annotation> annotationType() {
throw new UnsupportedOperationException("Method annotationType not implemented in " + getClass());
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
index 68d882d2b204..d3e9d1c03d2e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java
@@ -19,10 +19,10 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.options.StreamProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.io.fs.IFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -31,7 +31,7 @@ import java.util.Set;
* @author mike
*/
public interface StateStorageManager {
- void addMacro(String macro, String expansion);
+ void addMacro(@NotNull String macro, @NotNull String expansion);
@Nullable
TrackingPathMacroSubstitutor getMacroSubstitutor();
@@ -40,8 +40,16 @@ public interface StateStorageManager {
StateStorage getStateStorage(@NotNull Storage storageSpec) throws StateStorageException;
@Nullable
+ StateStorage getStateStorage(@NotNull String fileSpec, @NotNull RoamingType roamingType);
+
+ @Deprecated
+ @Nullable
+ /**
+ * @deprecated Use {@link #getStateStorage(String, com.intellij.openapi.components.RoamingType)}
+ */
StateStorage getFileStateStorage(@NotNull String fileSpec);
+ @NotNull
Collection<String> getStorageFileNames();
void clearStateStorage(@NotNull String file);
@@ -57,7 +65,7 @@ public interface StateStorageManager {
@Nullable
StateStorage getOldStorage(Object component, String componentName, StateStorageOperation operation) throws StateStorageException;
- @Nullable
+ @NotNull
String expandMacros(@NotNull String file);
@Deprecated
@@ -81,11 +89,11 @@ public interface StateStorageManager {
Set<String> analyzeExternalChanges(@NotNull Set<Pair<VirtualFile, StateStorage>> files);
@NotNull
- List<IFile> getAllStorageFilesToSave() throws StateStorageException;
+ List<File> getAllStorageFilesToSave() throws StateStorageException;
@NotNull
- List<IFile> getAllStorageFiles();
+ List<File> getAllStorageFiles();
void save() throws StateStorageException;
}
-} \ No newline at end of file
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
index 431c9a97820c..651acce271c0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
@@ -24,12 +24,14 @@ import com.intellij.openapi.options.CurrentUserHolder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.RoamingTypeDisabled;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
-import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import gnu.trove.TObjectLongHashMap;
@@ -99,9 +101,14 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
@Override
- public synchronized void addMacro(String macro, String expansion) {
- // avoid hundreds of $MODULE_FILE$ instances
- myMacros.put(("$" + macro + "$").intern(), expansion);
+ public synchronized void addMacro(@NotNull String macro, @NotNull String expansion) {
+ assert !macro.isEmpty();
+ // backward compatibility
+ if (macro.charAt(0) != '$') {
+ LOG.warn("Add macros instead of macro name: " + macro);
+ expansion = '$' + macro + '$';
+ }
+ myMacros.put(macro, expansion);
}
@Override
@@ -123,15 +130,15 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
}
- @Override
@Nullable
- public StateStorage getFileStateStorage(@NotNull String fileName) {
+ @Override
+ public StateStorage getStateStorage(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
myStorageLock.lock();
try {
- StateStorage stateStorage = myStorages.get(fileName);
+ StateStorage stateStorage = myStorages.get(fileSpec);
if (stateStorage == null) {
- stateStorage = createFileStateStorage(fileName);
- putStorageToMap(fileName, stateStorage);
+ stateStorage = createFileStateStorage(fileSpec, roamingType);
+ putStorageToMap(fileSpec, stateStorage);
}
return stateStorage;
}
@@ -141,6 +148,13 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
@Override
+ @Nullable
+ public StateStorage getFileStateStorage(@NotNull String fileSpec) {
+ return getStateStorage(fileSpec, RoamingType.PER_USER);
+ }
+
+ @NotNull
+ @Override
public Collection<String> getStorageFileNames() {
myStorageLock.lock();
try {
@@ -176,19 +190,19 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Nullable
private StateStorage createStateStorage(Storage storageSpec) throws StateStorageException {
- if (!storageSpec.storageClass().equals(StorageAnnotationsDefaultValues.NullStateStorage.class)) {
+ if (!storageSpec.storageClass().equals(StateStorage.class)) {
String key = UUID.randomUUID().toString();
((MutablePicoContainer)myPicoContainer).registerComponentImplementation(key, storageSpec.storageClass());
return (StateStorage)myPicoContainer.getComponentInstance(key);
}
- if (!storageSpec.stateSplitter().equals(StorageAnnotationsDefaultValues.NullStateSplitter.class)) {
+ if (!storageSpec.stateSplitter().equals(StateSplitter.class)) {
return createDirectoryStateStorage(storageSpec.file(), storageSpec.stateSplitter());
}
- return createFileStateStorage(storageSpec.file());
+ return createFileStateStorage(storageSpec.file(), storageSpec.roamingType());
}
private static String getStorageSpecId(Storage storageSpec) {
- if (!storageSpec.storageClass().equals(StorageAnnotationsDefaultValues.NullStateStorage.class)) {
+ if (!storageSpec.storageClass().equals(StateStorage.class)) {
return storageSpec.storageClass().getName();
}
else {
@@ -209,41 +223,30 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Nullable
private StateStorage createDirectoryStateStorage(String file, Class<? extends StateSplitter> splitterClass) throws StateStorageException {
- String expandedFile = expandMacros(file);
- if (expandedFile == null) {
- myStorages.put(file, null);
- return null;
- }
-
final StateSplitter splitter;
try {
- splitter = splitterClass.newInstance();
+ splitter = ReflectionUtil.newInstance(splitterClass);
}
- catch (InstantiationException e) {
+ catch (RuntimeException e) {
throw new StateStorageException(e);
}
- catch (IllegalAccessException e) {
- throw new StateStorageException(e);
- }
-
- return new DirectoryBasedStorage(myPathMacroSubstitutor, expandedFile, splitter, this, myPicoContainer);
+ return new DirectoryBasedStorage(myPathMacroSubstitutor, expandMacros(file), splitter, this, myPicoContainer);
}
@Nullable
- private StateStorage createFileStateStorage(@NotNull final String fileSpec) {
+ private StateStorage createFileStateStorage(@NotNull final String fileSpec, @Nullable RoamingType roamingType) {
String expandedFile = expandMacros(fileSpec);
- if (expandedFile == null) {
- myStorages.put(fileSpec, null);
- return null;
- }
- String extension = FileUtilRt.getExtension(new File(expandedFile).getName());
- if (!ourHeadlessEnvironment && extension.isEmpty()) {
+ if (!ourHeadlessEnvironment && PathUtilRt.getFileName(expandedFile).lastIndexOf('.') < 0) {
throw new IllegalArgumentException("Extension is missing for storage file: " + expandedFile);
}
- return new FileBasedStorage(getMacroSubstitutor(fileSpec), getStreamProvider(), expandedFile, fileSpec, myRootTagName, this,
- myPicoContainer, ComponentRoamingManager.getInstance(), this) {
+ if (roamingType != RoamingType.PER_USER && fileSpec.equals(StoragePathMacros.WORKSPACE_FILE)) {
+ roamingType = RoamingType.DISABLED;
+ }
+
+ return new FileBasedStorage(expandedFile, fileSpec, roamingType, getMacroSubstitutor(fileSpec), myRootTagName, this,
+ myPicoContainer, getStreamProvider(), this) {
@Override
@NotNull
protected StorageData createStorageData() {
@@ -271,8 +274,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
String filePath = getNotNullVersionsFilePath();
if (filePath != null) {
try {
- Document document = JDOMUtil.loadDocument(new File(filePath));
- loadComponentVersions(result, document);
+ loadComponentVersions(result, JDOMUtil.loadDocument(new File(filePath)));
}
catch (JDOMException e) {
LOG.debug(e);
@@ -294,6 +296,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
public static void loadComponentVersions(TObjectLongHashMap<String> result, Document document) {
List<Element> componentObjects = document.getRootElement().getChildren("component");
+ result.ensureCapacity(componentObjects.size());
for (Element component : componentObjects) {
String name = component.getAttributeValue("name");
String version = component.getAttributeValue("version");
@@ -330,26 +333,21 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
private static final Pattern MACRO_PATTERN = Pattern.compile("(\\$[^\\$]*\\$)");
@Override
- @Nullable
+ @NotNull
public synchronized String expandMacros(@NotNull String file) {
- final Matcher matcher = MACRO_PATTERN.matcher(file);
+ Matcher matcher = MACRO_PATTERN.matcher(file);
while (matcher.find()) {
String m = matcher.group(1);
- if (!myMacros.containsKey(m) || !ApplicationManager.getApplication().isUnitTestMode() && myMacros.get(m) == null) {
- throw new IllegalArgumentException("Unknown macro: " + m + " in storage spec: " + file);
+ if (!myMacros.containsKey(m)) {
+ throw new IllegalArgumentException("Unknown macro: " + m + " in storage file spec: " + file);
}
}
- String actualFile = file;
-
+ String expanded = file;
for (String macro : myMacros.keySet()) {
- final String replacement = myMacros.get(macro);
- if (replacement != null) {
- actualFile = StringUtil.replace(actualFile, macro, replacement);
- }
+ expanded = StringUtil.replace(expanded, macro, myMacros.get(macro));
}
-
- return actualFile;
+ return expanded;
}
@NotNull
@@ -424,7 +422,9 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Override
@Nullable
public StateStorage getOldStorage(Object component, String componentName, StateStorageOperation operation) throws StateStorageException {
- return getFileStateStorage(getOldStorageSpec(component, componentName, operation));
+ String oldStorageSpec = getOldStorageSpec(component, componentName, operation);
+ //noinspection deprecation
+ return oldStorageSpec == null ? null : getStateStorage(oldStorageSpec, component instanceof RoamingTypeDisabled ? RoamingType.DISABLED : RoamingType.PER_USER);
}
@Nullable
@@ -440,14 +440,14 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Override
@NotNull
- public List<IFile> getAllStorageFilesToSave() throws StateStorageException {
+ public List<File> getAllStorageFilesToSave() throws StateStorageException {
assert mySession == this;
return myCompoundSaveSession.getAllStorageFilesToSave();
}
@Override
@NotNull
- public List<IFile> getAllStorageFiles() {
+ public List<File> getAllStorageFiles() {
return myCompoundSaveSession.getAllStorageFiles();
}
@@ -503,15 +503,16 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
public void save() {
- if (!isDirty) return;
+ if (!isDirty) {
+ return;
+ }
+
String filePath = getNotNullVersionsFilePath();
if (filePath != null) {
- File dir = new File(filePath).getParentFile();
- if (!dir.isDirectory() && !dir.mkdirs()) {
- LOG.warn("Unable to create: " + dir);
- }
+ File file = new File(filePath);
+ FileUtilRt.createParentDirs(file);
try {
- JDOMUtil.writeDocument(new Document(createComponentVersionsXml(getComponentVersions())), filePath, "\n");
+ JDOMUtil.writeParent(createComponentVersionsXml(getComponentVersions()), file, "\n");
isDirty = false;
}
catch (IOException e) {
@@ -546,6 +547,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
return root;
}
+ @SuppressWarnings("deprecation")
private static class OldStreamProviderManager extends StreamProvider implements CurrentUserHolder {
private final List<OldStreamProviderAdapter> myStreamProviders = new SmartList<OldStreamProviderAdapter>();
@@ -575,22 +577,17 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
}
@Override
- public boolean saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException {
- boolean result = false;
+ public void saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException {
for (StreamProvider streamProvider : myStreamProviders) {
try {
- if (streamProvider.isEnabled() && streamProvider.isApplicable(fileSpec, roamingType) && streamProvider.saveContent(fileSpec, content, size, roamingType, async)) {
- result = true;
+ if (streamProvider.isEnabled() && streamProvider.isApplicable(fileSpec, roamingType)) {
+ streamProvider.saveContent(fileSpec, content, size, roamingType, async);
}
}
- catch (ConnectException e) {
- LOG.debug("Cannot send user profile to server: " + e.getLocalizedMessage());
- }
catch (Exception e) {
LOG.debug(e);
}
}
- return result;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
index bd732705446a..2344c8526b0a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.editor.DocumentRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.project.ex.ProjectEx;
-import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
@@ -38,7 +37,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SystemProperties;
import com.intellij.util.UniqueFileNamesProvider;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.io.fs.IFile;
import com.intellij.util.ui.UIUtil;
import org.jdom.Document;
import org.jdom.Element;
@@ -59,11 +57,12 @@ import java.util.Set;
* @author mike
*/
public class StorageUtil {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.StorageUtil");
+ private static final Logger LOG = Logger.getInstance(StorageUtil.class);
private static final boolean DUMP_COMPONENT_STATES = SystemProperties.getBooleanProperty("idea.log.externally.changed.component.states", false);
@SuppressWarnings("SpellCheckingInspection")
private static final SimpleDateFormat LOG_DIR_FORMAT = new SimpleDateFormat("yyyyMMdd-HHmmss");
+ private static final Pair<byte[], String> NON_EXISTENT_FILE_DATA = Pair.create(null, SystemProperties.getLineSeparator());
private StorageUtil() { }
@@ -110,34 +109,86 @@ public class StorageUtil {
return notified;
}
+
+ public static boolean isEmpty(@Nullable Parent element) {
+ if (element == null) {
+ return true;
+ }
+ else if (element instanceof Element) {
+ return JDOMUtil.isEmpty((Element)element);
+ }
+ else {
+ Document document = (Document)element;
+ return !document.hasRootElement() || JDOMUtil.isEmpty(document.getRootElement());
+ }
+ }
+
+ /**
+ * Due to historical reasons files in ROOT_CONFIG don’t wrapped into document (xml prolog) opposite to files in APP_CONFIG
+ */
@Nullable
- static VirtualFile save(@NotNull IFile file, Parent element, Object requestor) throws StateStorageException {
- try {
- String lineSeparator;
- String oldText;
- if (file.exists()) {
- VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
- Couple<String> pair = loadFile(vFile);
- lineSeparator = pair.second;
- oldText = pair.first;
+ static VirtualFile save(@NotNull File file, @Nullable Parent element, Object requestor, boolean wrapAsDocument, @Nullable VirtualFile cachedVirtualFile) throws StateStorageException {
+ if (isEmpty(element)) {
+ if (!file.exists()) {
+ return null;
+ }
+
+ VirtualFile virtualFile = cachedVirtualFile;
+ if (virtualFile == null || !virtualFile.isValid()) {
+ virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
+ }
+ if (virtualFile == null) {
+ LOG.info("Cannot find virtual file " + file.getAbsolutePath());
+ FileUtil.delete(file);
}
else {
- oldText = null;
- lineSeparator = SystemProperties.getLineSeparator();
- file.createParentDirs();
+ AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(DocumentRunnable.IgnoreDocumentRunnable.class);
+ try {
+ virtualFile.delete(requestor);
+ }
+ catch (IOException e) {
+ throw new StateStorageException(e);
+ }
+ finally {
+ token.finish();
+ }
}
+ return null;
+ }
- String text = JDOMUtil.writeParent(element, lineSeparator);
- if (text.equals(oldText)) {
- return null;
+ VirtualFile virtualFile = cachedVirtualFile == null || !cachedVirtualFile.isValid() ? null : cachedVirtualFile;
+ Parent document = !wrapAsDocument || element instanceof Document ? element : new Document((Element)element);
+ try {
+ BufferExposingByteArrayOutputStream byteOut;
+ if (file.exists()) {
+ if (virtualFile == null) {
+ virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ }
+
+ Pair<byte[], String> pair = loadFile(virtualFile);
+ byteOut = writeToBytes(document, pair.second);
+ if (equal(pair.first, byteOut)) {
+ return null;
+ }
+ }
+ else {
+ FileUtil.createParentDirs(file);
+ byteOut = writeToBytes(document, SystemProperties.getLineSeparator());
}
// mark this action as modifying the file which daemon analyzer should ignore
AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(DocumentRunnable.IgnoreDocumentRunnable.class);
try {
- VirtualFile virtualFile = getOrCreateVirtualFile(requestor, file);
- byte[] bytes = text.getBytes(CharsetToolkit.UTF8);
- virtualFile.setBinaryContent(bytes, -1, -1, requestor);
+ if (virtualFile == null) {
+ virtualFile = getOrCreateVirtualFile(requestor, file);
+ }
+ OutputStream virtualFileOut = virtualFile.getOutputStream(requestor);
+ try {
+ byteOut.writeTo(virtualFileOut);
+ }
+ finally {
+ virtualFileOut.close();
+ }
return virtualFile;
}
finally {
@@ -150,70 +201,78 @@ public class StorageUtil {
}
@NotNull
- static VirtualFile getOrCreateVirtualFile(final Object requestor, final IFile ioFile) throws IOException {
- VirtualFile vFile = getVirtualFile(ioFile);
-
- if (vFile == null) {
- vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
- }
+ private static BufferExposingByteArrayOutputStream writeToBytes(@NotNull Parent element, @NotNull String lineSeparator) throws IOException {
+ BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(512);
+ JDOMUtil.writeParent(element, out, lineSeparator);
+ return out;
+ }
- if (vFile == null) {
- final IFile parentFile = ioFile.getParentFile();
- final VirtualFile parentVFile =
- LocalFileSystem.getInstance().refreshAndFindFileByIoFile(parentFile); // need refresh if the directory has just been created
- if (parentVFile == null) {
- throw new IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile.getPath()));
+ @NotNull
+ static VirtualFile getOrCreateVirtualFile(@Nullable Object requestor, @NotNull File ioFile) throws IOException {
+ VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
+ if (virtualFile == null) {
+ File parentFile = ioFile.getParentFile();
+ // need refresh if the directory has just been created
+ VirtualFile parentVirtualFile = parentFile == null ? null : LocalFileSystem.getInstance().refreshAndFindFileByIoFile(parentFile);
+ if (parentVirtualFile == null) {
+ throw new IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile == null ? "" : parentFile.getPath()));
}
- vFile = parentVFile.createChildData(requestor, ioFile.getName());
+ virtualFile = parentVirtualFile.createChildData(requestor, ioFile.getName());
}
-
- return vFile;
- }
-
- @Nullable
- static VirtualFile getVirtualFile(final IFile ioFile) {
- return LocalFileSystem.getInstance().findFileByIoFile(ioFile);
+ return virtualFile;
}
/**
* @return pair.first - file contents (null if file does not exist), pair.second - file line separators
*/
- private static Couple<String> loadFile(@Nullable final VirtualFile file) throws IOException {
+ @NotNull
+ private static Pair<byte[], String> loadFile(@Nullable final VirtualFile file) throws IOException {
if (file == null || !file.exists()) {
- return Couple.of(null, SystemProperties.getLineSeparator());
+ return NON_EXISTENT_FILE_DATA;
}
- String fileText = new String(file.contentsToByteArray(), CharsetToolkit.UTF8);
- final int index = fileText.indexOf('\n');
- return Couple.of(fileText, index == -1
- ? SystemProperties.getLineSeparator()
- : index - 1 >= 0 ? fileText.charAt(index - 1) == '\r' ? "\r\n" : "\n" : "\n");
+ byte[] bytes = file.contentsToByteArray();
+ String lineSeparator = file.getDetectedLineSeparator();
+ if (lineSeparator == null) {
+ String fileText = new String(bytes, CharsetToolkit.UTF8);
+ final int index = fileText.indexOf('\n');
+ lineSeparator = index == -1
+ ? SystemProperties.getLineSeparator()
+ : index - 1 >= 0 ? fileText.charAt(index - 1) == '\r' ? "\r\n" : "\n" : "\n";
+ }
+ return Pair.create(bytes, lineSeparator);
}
- public static boolean contentEquals(@NotNull final Document document, @NotNull final VirtualFile file) {
+ public static boolean contentEquals(@NotNull Parent element, @NotNull VirtualFile file) {
+ return newContentIfDiffers(element, file) == null;
+ }
+
+ @Nullable
+ public static BufferExposingByteArrayOutputStream newContentIfDiffers(@NotNull Parent element, @Nullable VirtualFile file) {
try {
- final Couple<String> pair = loadFile(file);
- return pair.first != null && pair.first.equals(JDOMUtil.writeDocument(document, pair.second));
+ Pair<byte[], String> pair = loadFile(file);
+ BufferExposingByteArrayOutputStream out = writeToBytes(element, pair.second);
+ return pair.first != null && equal(pair.first, out) ? null : out;
}
catch (IOException e) {
LOG.debug(e);
- return false;
+ return null;
}
}
- public static boolean contentEquals(@NotNull final Element element, @NotNull final VirtualFile file) {
- try {
- final Couple<String> pair = loadFile(file);
- return pair.first != null && pair.first.equals(printElement(element, pair.second));
- }
- catch (IOException e) {
- LOG.debug(e);
+ public static boolean equal(byte[] a1, @NotNull BufferExposingByteArrayOutputStream out) {
+ int length = out.size();
+ if (a1.length != length) {
return false;
}
- }
- static String printElement(final Element element, final String lineSeparator) throws StateStorageException {
- return JDOMUtil.writeElement(element, lineSeparator);
+ byte[] internalBuffer = out.getInternalBuffer();
+ for (int i = 0; i < length; i++) {
+ if (a1[i] != internalBuffer[i]) {
+ return false;
+ }
+ }
+ return true;
}
@Nullable
@@ -229,6 +288,7 @@ public class StorageUtil {
}
}
+ @SuppressWarnings("Contract")
@Nullable
public static Document loadDocument(@Nullable InputStream stream) {
if (stream == null) {
@@ -252,29 +312,20 @@ public class StorageUtil {
}
@NotNull
- public static BufferExposingByteArrayOutputStream documentToBytes(@NotNull Document document, boolean useSystemLineSeparator) throws IOException {
- BufferExposingByteArrayOutputStream out = new BufferExposingByteArrayOutputStream(512);
- OutputStreamWriter writer = new OutputStreamWriter(out, CharsetToolkit.UTF8_CHARSET);
- try {
- JDOMUtil.writeDocument(document, writer, useSystemLineSeparator ? SystemProperties.getLineSeparator() : "\n");
- return out;
- }
- finally {
- writer.close();
- }
+ public static BufferExposingByteArrayOutputStream elementToBytes(@NotNull Parent element, boolean useSystemLineSeparator) throws IOException {
+ return writeToBytes(element, useSystemLineSeparator ? SystemProperties.getLineSeparator() : "\n");
}
- public static boolean sendContent(@NotNull StreamProvider provider, @NotNull String fileSpec, @NotNull Document copy, @NotNull RoamingType type, boolean async) {
+ public static void sendContent(@NotNull StreamProvider provider, @NotNull String fileSpec, @NotNull Parent element, @NotNull RoamingType type, boolean async) {
if (!provider.isApplicable(fileSpec, type)) {
- return false;
+ return;
}
try {
- return doSendContent(provider, fileSpec, copy, type, async);
+ doSendContent(provider, fileSpec, element, type, async);
}
catch (IOException e) {
LOG.warn(e);
- return false;
}
}
@@ -287,10 +338,10 @@ public class StorageUtil {
/**
* You must call {@link StreamProvider#isApplicable(String, com.intellij.openapi.components.RoamingType)} before
*/
- public static boolean doSendContent(StreamProvider provider, String fileSpec, Document copy, RoamingType type, boolean async) throws IOException {
+ public static void doSendContent(@NotNull StreamProvider provider, @NotNull String fileSpec, @NotNull Parent element, @NotNull RoamingType type, boolean async) throws IOException {
// we should use standard line-separator (\n) - stream provider can share file content on any OS
- BufferExposingByteArrayOutputStream content = documentToBytes(copy, false);
- return provider.saveContent(fileSpec, content.getInternalBuffer(), content.size(), type, async);
+ BufferExposingByteArrayOutputStream content = elementToBytes(element, false);
+ provider.saveContent(fileSpec, content.getInternalBuffer(), content.size(), type, async);
}
public static void logStateDiffInfo(Set<Pair<VirtualFile, StateStorage>> changedFiles, Set<String> componentNames) {
@@ -309,10 +360,9 @@ public class StorageUtil {
StateStorage storage = pair.second;
if (storage instanceof XmlElementStorage) {
- Document state = ((XmlElementStorage)storage).logComponents();
+ Element state = ((XmlElementStorage)storage).logComponents();
if (state != null) {
- File logFile = new File(logDirectory, "prev_" + file.getName());
- JDOMUtil.writeDocument(state, logFile, "\n");
+ JDOMUtil.writeParent(state, new File(logDirectory, "prev_" + file.getName()), "\n");
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
index ec57d8c63601..cf49b927ad0e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.java
@@ -12,7 +12,9 @@ import java.util.Collections;
public abstract class StreamProvider {
public static final StreamProvider[] EMPTY_ARRAY = new StreamProvider[0];
- public abstract boolean isEnabled();
+ public boolean isEnabled() {
+ return true;
+ }
/**
* If true, special version file per storage file will keep version of component.
@@ -37,7 +39,7 @@ public abstract class StreamProvider {
* @param roamingType
* @param async
*/
- public abstract boolean saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException;
+ public abstract void saveContent(@NotNull String fileSpec, @NotNull byte[] content, int size, @NotNull RoamingType roamingType, boolean async) throws IOException;
@Nullable
public abstract InputStream loadContent(@NotNull String fileSpec, @NotNull RoamingType roamingType) throws IOException;
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java
index b028676168d5..76f47db77533 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java
@@ -15,44 +15,48 @@
*/
package com.intellij.openapi.components.impl.stores;
-import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.options.CurrentUserHolder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.SafeWriteRequestor;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
+import gnu.trove.THashSet;
import gnu.trove.TObjectLongHashMap;
import org.jdom.Document;
import org.jdom.Element;
+import org.jdom.JDOMException;
import org.jdom.filter.ElementFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.util.*;
public abstract class XmlElementStorage implements StateStorage, Disposable {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.XmlElementStorage");
+ private static final Logger LOG = Logger.getInstance(XmlElementStorage.class);
+
+ private final static RoamingElementFilter DISABLED_ROAMING_ELEMENT_FILTER = new RoamingElementFilter(RoamingType.DISABLED);
private static final String ATTR_NAME = "name";
private static final String VERSION_FILE_SUFFIX = ".ver";
protected TrackingPathMacroSubstitutor myPathMacroSubstitutor;
- @NotNull private final String myRootElementName;
+ @NotNull protected final String myRootElementName;
private Object mySession;
private StorageData myLoadedData;
protected final StreamProvider myStreamProvider;
protected final String myFileSpec;
- private final ComponentRoamingManager myComponentRoamingManager;
protected boolean myBlockSavingTheContent = false;
protected int myUpToDateHash = -1;
- protected int myProviderUpToDateHash = -1;
+ private int myProviderUpToDateHash = -1;
private boolean mySavingDisabled = false;
private final Map<String, Object> myStorageComponentStates = new THashMap<String, Object>(); // at load we store Element, on setState Integer of hash
@@ -60,6 +64,8 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
private final ComponentVersionProvider myLocalVersionProvider;
protected final RemoteComponentVersionProvider myRemoteVersionProvider;
+ private final RoamingType myRoamingType;
+
protected ComponentVersionListener myListener = new ComponentVersionListener(){
@Override
public void componentStateChanged(String componentName) {
@@ -69,18 +75,18 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
private boolean myDisposed;
- protected XmlElementStorage(@Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor,
+ protected XmlElementStorage(@NotNull String fileSpec,
+ @Nullable RoamingType roamingType,
+ @Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor,
@NotNull Disposable parentDisposable,
@NotNull String rootElementName,
@Nullable StreamProvider streamProvider,
- String fileSpec,
- ComponentRoamingManager componentRoamingManager,
ComponentVersionProvider componentVersionProvider) {
+ myFileSpec = fileSpec;
+ myRoamingType = roamingType == null ? RoamingType.PER_USER : roamingType;
myPathMacroSubstitutor = pathMacroSubstitutor;
myRootElementName = rootElementName;
- myStreamProvider = streamProvider;
- myFileSpec = fileSpec;
- myComponentRoamingManager = componentRoamingManager;
+ myStreamProvider = myRoamingType == RoamingType.DISABLED ? null : streamProvider;
Disposer.register(parentDisposable, this);
myLocalVersionProvider = componentVersionProvider;
@@ -92,36 +98,39 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
@Nullable
- protected abstract Document loadDocument() throws StateStorageException;
+ protected abstract Element loadLocalData();
@Nullable
- public synchronized Element getState(final String componentName) throws StateStorageException {
+ public synchronized Element getState(@NotNull String componentName) {
final StorageData storageData = getStorageData(false);
final Element state = storageData.getState(componentName);
-
if (state != null) {
if (!myStorageComponentStates.containsKey(componentName)) {
myStorageComponentStates.put(componentName, state);
}
storageData.removeState(componentName);
}
-
return state;
}
@Override
- public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
+ public boolean hasState(final Object component, @NotNull String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
return getStorageData(reloadData).hasState(componentName);
}
@Override
@Nullable
- public <T> T getState(final Object component, final String componentName, Class<T> stateClass, @Nullable T mergeInto) throws StateStorageException {
+ public <T> T getState(final Object component, @NotNull String componentName, Class<T> stateClass, @Nullable T mergeInto) throws StateStorageException {
return DefaultStateSerializer.deserializeState(getState(componentName), stateClass, mergeInto);
}
@NotNull
- protected StorageData getStorageData(final boolean reloadData) throws StateStorageException {
+ protected StorageData getStorageData() {
+ return getStorageData(false);
+ }
+
+ @NotNull
+ private StorageData getStorageData(boolean reloadData) {
if (myLoadedData != null && !reloadData) {
return myLoadedData;
}
@@ -131,48 +140,48 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
@NotNull
- protected StorageData loadData(boolean useProvidersData) throws StateStorageException {
- Document document = loadDocument();
+ protected StorageData loadData(boolean useProvidersData) {
StorageData result = createStorageData();
- if (document != null) {
- loadState(result, document.getRootElement());
- }
-
if (useProvidersData && myStreamProvider != null && myStreamProvider.isEnabled()) {
- for (RoamingType roamingType : RoamingType.values()) {
- if (roamingType != RoamingType.DISABLED && roamingType != RoamingType.GLOBAL) {
- try {
- Document sharedDocument = StorageUtil.loadDocument(myStreamProvider.loadContent(myFileSpec, roamingType));
- if (sharedDocument != null) {
- filterOutOfDate(sharedDocument.getRootElement());
- loadState(result, sharedDocument.getRootElement());
- }
- }
- catch (Exception e) {
- LOG.warn(e);
- }
- }
+ boolean wasLoaded = false;
+ try {
+ wasLoaded = loadDataFromStreamProvider(result);
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ }
+
+ //noinspection deprecation
+ if (wasLoaded && !myStreamProvider.isVersioningRequired() && !(myStreamProvider instanceof OldStreamProviderAdapter || myStreamProvider instanceof CurrentUserHolder)) {
+ // we don't use local data if stream provider has one (to preserve backward compatibility, we don't use this logic for old stream providers)
+ return result;
}
}
+ Element element = loadLocalData();
+ if (element != null) {
+ loadState(result, element);
+ }
+
return result;
}
- protected void loadState(final StorageData result, final Element element) throws StateStorageException {
- if (myPathMacroSubstitutor != null) {
- myPathMacroSubstitutor.expandPaths(element);
+ private boolean loadDataFromStreamProvider(@NotNull StorageData result) throws IOException, JDOMException {
+ assert myStreamProvider != null;
+ InputStream inputStream = myStreamProvider.loadContent(myFileSpec, myRoamingType);
+ if (inputStream == null) {
+ return false;
}
- IdeaPluginDescriptorImpl.internJDOMElement(element);
+ Element element = JDOMUtil.loadDocument(inputStream).getRootElement();
+ filterOutOfDate(element);
+ loadState(result, element);
+ return true;
+ }
- try {
- result.load(element);
- result.checkUnknownMacros(myPathMacroSubstitutor);
- }
- catch (IOException e) {
- throw new StateStorageException(e);
- }
+ private void loadState(@NotNull StorageData result, @NotNull Element element) {
+ result.load(element, myPathMacroSubstitutor, true);
}
@NotNull
@@ -182,25 +191,15 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
public void setDefaultState(final Element element) {
myLoadedData = createStorageData();
- try {
- loadState(myLoadedData, element);
- }
- catch (StateStorageException e) {
- LOG.error(e);
- }
+ loadState(myLoadedData, element);
}
@Override
@NotNull
public ExternalizationSession startExternalization() {
- try {
- final ExternalizationSession session = new MyExternalizationSession(getStorageData(false).clone(), myListener);
- mySession = session;
- return session;
- }
- catch (StateStorageException e) {
- throw new RuntimeException(e);
- }
+ ExternalizationSession session = new MyExternalizationSession(getStorageData().clone(), myListener);
+ mySession = session;
+ return session;
}
@Override
@@ -226,19 +225,19 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
@NotNull
@Override
- public Collection<IFile> getStorageFilesToSave() throws StateStorageException {
+ public Collection<File> getStorageFilesToSave() throws StateStorageException {
return Collections.emptySet();
}
@NotNull
@Override
- public List<IFile> getAllStorageFiles() {
+ public List<File> getAllStorageFiles() {
return Collections.emptyList();
}
};
}
- protected abstract MySaveSession createSaveSession(final MyExternalizationSession externalizationSession);
+ protected abstract MySaveSession createSaveSession(MyExternalizationSession externalizationSession);
@Override
public void finishSave(@NotNull final SaveSession saveSession) {
@@ -265,22 +264,26 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
@Override
- public void setState(@NotNull final Object component, final String componentName, @NotNull final Object state, final Storage storageSpec) throws StateStorageException {
+ public void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, @Nullable Storage storageSpec) {
assert mySession == this;
+ Element element;
try {
- setState(componentName, DefaultStateSerializer.serializeState(state, storageSpec));
+ element = DefaultStateSerializer.serializeState(state, storageSpec);
}
catch (WriteExternalException e) {
LOG.debug(e);
+ return;
}
- }
- private synchronized void setState(final String componentName, final Element element) {
- if (element.getAttributes().isEmpty() && element.getChildren().isEmpty()) {
+ if (element == null || JDOMUtil.isEmpty(element)) {
return;
}
+ setState(componentName, element);
+ }
+
+ private synchronized void setState(@NotNull String componentName, @NotNull Element element) {
myStorageData.setState(componentName, element);
int hash = JDOMUtil.getTreeHash(element);
try {
@@ -296,8 +299,12 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
}
- protected Document getDocument(StorageData data) {
- final Element element = data.save();
+ @Nullable
+ protected Element getElement(@NotNull StorageData data) {
+ Element element = data.save();
+ if (element == null || JDOMUtil.isEmpty(element)) {
+ return null;
+ }
if (myPathMacroSubstitutor != null) {
try {
@@ -308,18 +315,18 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
}
- return new Document(element);
+ return element;
}
protected abstract class MySaveSession implements SaveSession, SafeWriteRequestor {
final StorageData myStorageData;
- private Document myDocumentToSave;
+ private Element myElementToSave;
public MySaveSession(MyExternalizationSession externalizationSession) {
myStorageData = externalizationSession.myStorageData;
}
- public final boolean needsSave() throws StateStorageException {
+ public final boolean needsSave() {
assert mySession == this;
return _needsSave(calcHash());
}
@@ -382,11 +389,10 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
try {
if (myStreamProvider != null && myStreamProvider.isEnabled() && (myProviderUpToDateHash == -1 || myProviderUpToDateHash != hash)) {
try {
- //noinspection IfStatementWithIdenticalBranches
- if (saveForProvider(myStreamProvider)) {
- //noinspection UnnecessaryReturnStatement
- return;
- }
+ saveForProvider();
+ }
+ catch (IOException e) {
+ LOG.warn(e);
}
finally {
myProviderUpToDateHash = hash;
@@ -398,9 +404,9 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
}
- private void saveLocally(final Integer hash) {
+ private void saveLocally(int hash) {
try {
- if (!isHashUpToDate(hash) && _needsSave(hash)) {
+ if (!(myUpToDateHash != -1 && myUpToDateHash == hash) && _needsSave(hash)) {
doSave();
}
}
@@ -409,15 +415,15 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
}
- private boolean saveForProvider(@NotNull StreamProvider streamProvider) {
- if (!streamProvider.isApplicable(myFileSpec, RoamingType.PER_USER)) {
- return false;
+ private void saveForProvider() throws IOException {
+ if (!myStreamProvider.isApplicable(myFileSpec, myRoamingType)) {
+ return;
}
- Document document = getDocumentToSave();
- Element rootElement = document.getRootElement();
- if (rootElement.getChildren().isEmpty()) {
- return false;
+ Element element = getElementToSave();
+ if (element == null || element.getChildren().isEmpty()) {
+ myStreamProvider.delete(myFileSpec, myRoamingType);
+ return;
}
// skip the whole document if some component has disabled roaming type
@@ -425,59 +431,34 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
// one exclusion: workspace file (you don't have choice in this case)
// for example, it is important for ICS ProjectId - we cannot keep project in another place,
// but this project id must not be shared
- if (!myFileSpec.equals(StoragePathMacros.WORKSPACE_FILE) &&
- rootElement.getContent(new RoamingElementFilter(RoamingType.DISABLED)).iterator().hasNext()) {
- return false;
- }
-
- RoamingElementFilter perPlatformFilter = new RoamingElementFilter(RoamingType.PER_PLATFORM);
- if (rootElement.getContent(perPlatformFilter).iterator().hasNext()) {
- return doSaveForProvider(rootElement, new RoamingElementFilter(RoamingType.PER_USER)) ||
- doSaveForProvider(rootElement, perPlatformFilter);
+ if (myFileSpec.equals(StoragePathMacros.WORKSPACE_FILE)) {
+ Element copiedElement = JDOMUtil.cloneElement(element, DISABLED_ROAMING_ELEMENT_FILTER);
+ if (copiedElement != null) {
+ doSaveForProvider(copiedElement, DISABLED_ROAMING_ELEMENT_FILTER.myRoamingType, myStreamProvider);
+ }
}
else {
- return doSaveForProvider(document, RoamingType.PER_USER, streamProvider);
+ doSaveForProvider(element, myRoamingType, myStreamProvider);
}
}
- private boolean doSaveForProvider(Element element, RoamingElementFilter filter) {
- Element copiedElement = JDOMUtil.cloneElement(element, filter);
- return copiedElement != null && doSaveForProvider(new Document(copiedElement), filter.myRoamingType, myStreamProvider);
- }
-
- private boolean doSaveForProvider(Document actualDocument, RoamingType roamingType, StreamProvider streamProvider) {
- try {
- boolean result = StorageUtil.doSendContent(streamProvider, myFileSpec, actualDocument, roamingType, true);
- if (streamProvider.isVersioningRequired()) {
- TObjectLongHashMap<String> versions = loadVersions(actualDocument.getRootElement().getChildren(StorageData.COMPONENT));
- if (!versions.isEmpty()) {
- Document versionDoc = new Document(StateStorageManagerImpl.createComponentVersionsXml(versions));
- StorageUtil.doSendContent(streamProvider, myFileSpec + VERSION_FILE_SUFFIX, versionDoc, roamingType, true);
- }
+ private void doSaveForProvider(@NotNull Element element, @NotNull RoamingType roamingType, @NotNull StreamProvider streamProvider) throws IOException {
+ StorageUtil.doSendContent(streamProvider, myFileSpec, element, roamingType, true);
+ if (streamProvider.isVersioningRequired()) {
+ TObjectLongHashMap<String> versions = loadVersions(element.getChildren(StorageData.COMPONENT));
+ if (!versions.isEmpty()) {
+ Element versionDoc = StateStorageManagerImpl.createComponentVersionsXml(versions);
+ StorageUtil.doSendContent(streamProvider, myFileSpec + VERSION_FILE_SUFFIX, versionDoc, roamingType, true);
}
- return result;
- }
- catch (IOException e) {
- LOG.warn(e);
- return false;
}
}
- private boolean isHashUpToDate(final Integer hash) {
- return myUpToDateHash != -1 && myUpToDateHash == hash;
- }
-
- protected Document getDocumentToSave() {
- if (myDocumentToSave != null) return myDocumentToSave;
-
- final Element element = myStorageData.save();
- myDocumentToSave = new Document(element);
-
- if (myPathMacroSubstitutor != null) {
- myPathMacroSubstitutor.collapsePaths(element);
+ @Nullable
+ protected Element getElementToSave() {
+ if (myElementToSave == null) {
+ myElementToSave = getElement(myStorageData);
}
-
- return myDocumentToSave;
+ return myElementToSave;
}
public StorageData getData() {
@@ -488,12 +469,12 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
@Nullable
public Set<String> analyzeExternalChanges(@NotNull final Set<Pair<VirtualFile,StateStorage>> changedFiles) {
try {
- Document document = loadDocument();
+ Element element = loadLocalData();
StorageData storageData = createStorageData();
- if (document == null) {
+ if (element == null) {
return Collections.emptySet();
}
- loadState(storageData, document.getRootElement());
+ loadState(storageData, element);
return storageData.getDifference(myStorageData, myPathMacroSubstitutor);
}
catch (StateStorageException e) {
@@ -502,21 +483,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
return null;
}
-
- private class RoamingElementFilter extends ElementFilter {
- final RoamingType myRoamingType;
-
- public RoamingElementFilter(RoamingType roamingType) {
- super(StorageData.COMPONENT);
-
- myRoamingType = roamingType;
- }
-
- @Override
- public boolean matches(Object obj) {
- return super.matches(obj) && myComponentRoamingManager.getRoamingType(((Element)obj).getAttributeValue(StorageData.NAME)) == myRoamingType;
- }
- }
}
private TObjectLongHashMap<String> loadVersions(List<Element> elements) {
@@ -545,11 +511,9 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
@Override
public void reload(@NotNull final Set<String> changedComponents) throws StateStorageException {
final StorageData storageData = loadData(false);
-
final StorageData oldLoadedData = myLoadedData;
-
if (oldLoadedData != null) {
- Set<String> componentsToRetain = new HashSet<String>(oldLoadedData.myComponentStates.keySet());
+ Set<String> componentsToRetain = new THashSet<String>(oldLoadedData.myComponentStates.keySet());
componentsToRetain.addAll(changedComponents);
// add empty configuration tags for removed components
@@ -568,7 +532,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
myLoadedData = storageData;
}
- private void filterOutOfDate(Element element) {
+ private void filterOutOfDate(@NotNull Element element) {
if (myRemoteVersionProvider == null) {
return;
}
@@ -587,12 +551,19 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
@Nullable
- Document logComponents() throws StateStorageException {
- return mySession instanceof MySaveSession ? getDocument(((MySaveSession)mySession).myStorageData) : null;
+ Element logComponents() {
+ return mySession instanceof MySaveSession ? getElement(((MySaveSession)mySession).myStorageData) : null;
}
- protected class RemoteComponentVersionProvider implements ComponentVersionProvider {
- protected TObjectLongHashMap<String> myProviderVersions;
+ public void resetProviderCache() {
+ myProviderUpToDateHash = -1;
+ if (myRemoteVersionProvider != null) {
+ myRemoteVersionProvider.myProviderVersions = null;
+ }
+ }
+
+ private final class RemoteComponentVersionProvider implements ComponentVersionProvider {
+ private TObjectLongHashMap<String> myProviderVersions;
@Override
public long getVersion(String name) {
@@ -632,4 +603,19 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
}
}
}
+
+ private static class RoamingElementFilter extends ElementFilter {
+ final RoamingType myRoamingType;
+
+ public RoamingElementFilter(RoamingType roamingType) {
+ super(StorageData.COMPONENT);
+
+ myRoamingType = roamingType;
+ }
+
+ @Override
+ public boolean matches(Object obj) {
+ return super.matches(obj) && ComponentRoamingManager.getInstance().getRoamingType(((Element)obj).getAttributeValue(StorageData.NAME)) == myRoamingType;
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java b/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java
index b508686ade00..369acf473cbc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ApplicationStarterBase.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileInputStream;
@@ -57,13 +58,13 @@ public abstract class ApplicationStarterBase extends ApplicationStarterEx {
}
@Override
- public void processExternalCommandLine(String[] args) {
+ public void processExternalCommandLine(String[] args, @Nullable String currentDirectory) {
if (!checkArguments(args)) {
Messages.showMessageDialog(getUsageMessage(), StringUtil.toTitleCase(getCommandName()), Messages.getInformationIcon());
return;
}
try {
- processCommand(args);
+ processCommand(args, currentDirectory);
}
catch (Exception e) {
Messages.showMessageDialog(String.format("Error showing %s: %s", getCommandName(), e.getMessage()),
@@ -86,7 +87,7 @@ public abstract class ApplicationStarterBase extends ApplicationStarterEx {
public abstract String getUsageMessage();
- protected abstract void processCommand(String[] args) throws Exception;
+ protected abstract void processCommand(String[] args, @Nullable String currentDirectory) throws Exception;
@Override
public void premain(String[] args) {
@@ -99,7 +100,7 @@ public abstract class ApplicationStarterBase extends ApplicationStarterEx {
@Override
public void main(String[] args) {
try {
- processCommand(args);
+ processCommand(args, null);
}
catch (Exception e) {
e.printStackTrace();
@@ -116,12 +117,12 @@ public abstract class ApplicationStarterBase extends ApplicationStarterEx {
System.exit(0);
}
- public static VirtualFile findOrCreateFile(String path) throws IOException {
+ public static VirtualFile findOrCreateFile(String path, @Nullable String currentDirectory) throws IOException {
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
if (file == null) {
boolean result = new File(path).createNewFile();
if (result) {
- return findFile(path);
+ return findFile(path, currentDirectory);
}
else {
throw new FileNotFoundException("Can't create file " + path);
@@ -167,11 +168,10 @@ public abstract class ApplicationStarterBase extends ApplicationStarterEx {
}
@NotNull
- public static VirtualFile findFile(final String path) throws OperationFailedException {
+ public static VirtualFile findFile(final String path, @Nullable String currentDirectory) throws OperationFailedException {
File ioFile = new File(path);
- if (!ioFile.exists()) {
- final String dir = PathManager.getOriginalWorkingDir();
- ioFile = new File(dir + File.separator + path);
+ if (!ioFile.isAbsolute() && currentDirectory != null) {
+ ioFile = new File(currentDirectory, path);
}
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
if (file == null) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java b/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java
index 742a405f350e..143df9617310 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/DiffApplication.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
/**
* @author max
@@ -37,11 +38,11 @@ public class DiffApplication extends ApplicationStarterBase {
return DiffBundle.message("diff.application.usage.parameters.and.description", scriptName);
}
- public void processCommand(String[] args) throws OperationFailedException {
+ public void processCommand(String[] args, @Nullable String currentDirectory) throws OperationFailedException {
final String path1 = args[1];
final String path2 = args[2];
- final VirtualFile file1 = findFile(path1);
- final VirtualFile file2 = findFile(path2);
+ final VirtualFile file1 = findFile(path1, currentDirectory);
+ final VirtualFile file2 = findFile(path2, currentDirectory);
final boolean areDirs = areDirs(file1, file2);
final boolean areJars = areJars(file1, file2);
if (areDirs || areJars) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java b/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java
index 0c088929ea49..d1d6cf6cb9f5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/MergeApplication.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.diff;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.Nullable;
/**
* @author Konstantin Bulenkov
@@ -34,11 +35,11 @@ public class MergeApplication extends ApplicationStarterBase {
}
@Override
- protected void processCommand(String[] args) throws Exception {
- final VirtualFile left = findFile(args[1]);
- final VirtualFile right = findFile(args[2]);
- final VirtualFile middle = findFile(args[3]);
- final VirtualFile result = findOrCreateFile(args.length == 4 ? args[3] : args[4]);
+ protected void processCommand(String[] args, @Nullable String currentDirectory) throws Exception {
+ final VirtualFile left = findFile(args[1], currentDirectory);
+ final VirtualFile right = findFile(args[2], currentDirectory);
+ final VirtualFile middle = findFile(args[3], currentDirectory);
+ final VirtualFile result = findOrCreateFile(args.length == 4 ? args[3] : args[4], currentDirectory);
MergeRequest request = DiffRequestFactory.getInstance()
.createMergeRequest(getText(left), getText(right), getText(middle), result,
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
index cc1be90ef046..dab14bdadcc2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ScrollToTheEndToolbarAction.java
@@ -48,7 +48,7 @@ public class ScrollToTheEndToolbarAction extends DumbAwareAction {
Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
Dimension size = myEditor.getContentComponent().getSize();
boolean isEndVisible = visibleArea.y + visibleArea.height >= size.height;
- boolean isOnLastLine = document.getLineNumber(caretOffset) == document.getLineCount() - 1;
+ boolean isOnLastLine = document.getLineCount() == 0 || document.getLineNumber(caretOffset) == document.getLineCount() - 1;
e.getPresentation().setEnabled(!isEndVisible || !isOnLastLine);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
index cf3c196a9d78..0d0377bdf7fe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
@@ -382,7 +382,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name
}
@Override
- public Document writeScheme(@NotNull final EditorColorsSchemeImpl scheme) {
+ public Element writeScheme(@NotNull final EditorColorsSchemeImpl scheme) {
Element root = new Element(SCHEME_NODE_NAME);
try {
scheme.writeExternal(root);
@@ -392,7 +392,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name
return null;
}
- return new Document(root);
+ return root;
}
@Override
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 51f6ec4a8cdb..165429ce56df 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
@@ -81,10 +81,7 @@ import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
-import com.intellij.util.ui.ButtonlessScrollBarUI;
-import com.intellij.util.ui.GraphicsUtil;
-import com.intellij.util.ui.MacUIUtil;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.*;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.UiNotifyConnector;
import gnu.trove.TIntArrayList;
@@ -4106,7 +4103,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void processMouseDragged(@NotNull MouseEvent e) {
- if (SwingUtilities.isRightMouseButton(e)) {
+ if (JBSwingUtilities.isRightMouseButton(e)) {
return;
}
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
index 5a9c704173aa..c4b9a38914cf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
@@ -56,7 +56,7 @@ public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory {
private void transformRangeMarkers(@NotNull DocumentEvent e) {
Document document = e.getDocument();
VirtualFile file = fileDocumentManager.getFile(document);
- if (file == null) {
+ if (file == null || myProject.isDisposed()) {
return;
}
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 731d1e26a289..574780a661c2 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
@@ -24,6 +24,7 @@
*/
package com.intellij.openapi.editor.impl;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
@@ -36,6 +37,7 @@ import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
@@ -464,6 +466,16 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
mySelectionListeners.add(listener);
}
+ public void addSelectionListener(final SelectionListener listener, Disposable parent) {
+ mySelectionListeners.add(listener);
+ Disposer.register(parent, new Disposable() {
+ @Override
+ public void dispose() {
+ mySelectionListeners.remove(listener);
+ }
+ });
+ }
+
@Override
public void removeSelectionListener(SelectionListener listener) {
boolean success = mySelectionListeners.remove(listener);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
index d585ec5a7b7d..2938f419909c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
@@ -114,16 +114,32 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
@Override
@NotNull
- public VirtualFile[] choose(@Nullable VirtualFile toSelect, Project project) {
+ public VirtualFile[] choose(@Nullable final Project project, @NotNull final VirtualFile... toSelect) {
init();
- if (myProject == null && project != null) {
+ if ((myProject == null) && (project != null)) {
myProject = project;
}
- restoreSelection(toSelect);
+ if (toSelect.length == 1) {
+ restoreSelection(toSelect[0]);
+ }
+ else if (toSelect.length == 0) {
+ restoreSelection(null); // select last opened file
+ }
+ else {
+ selectInTree(toSelect, true);
+ }
+
show();
return myChosenFiles;
}
+
+ @NotNull
+ @Override
+ public VirtualFile[] choose(@Nullable final VirtualFile toSelect, @Nullable final Project project) {
+ return choose(project, toSelect);
+ }
+
@Override
public void choose(@Nullable VirtualFile toSelect, @NotNull Consumer<List<VirtualFile>> callback) {
init();
@@ -163,7 +179,6 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
if (file != null && file.getFileSystem() instanceof LocalFileSystem) {
saveRecent(file.getPath());
}
-
}
protected void saveRecent(String path) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java
index 30eb78cf706f..c074a4965493 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java
@@ -164,6 +164,7 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B
public abstract boolean isInsideChange();
+ @Override
@Nullable
public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret) {
for (final EditorDataProvider dataProvider : myDataProviders) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
index 48a5b7c9a4dc..d8a704d891bf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.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.
@@ -66,7 +66,7 @@ public abstract class EditorComposite implements Disposable {
/**
* File for which composite is created
*/
- private final VirtualFile myFile;
+ @NotNull private final VirtualFile myFile;
/**
* Whether the composite is pinned or not
*/
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorEmptyTextPainter.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorEmptyTextPainter.java
index 4807812e5047..101f4a7ddfed 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorEmptyTextPainter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorEmptyTextPainter.java
@@ -54,9 +54,12 @@ public class EditorEmptyTextPainter {
UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f);
painter.withShadow(true, new JBColor(Gray._200.withAlpha(100), Gray._0.withAlpha(255)));
- painter.appendLine("No files are open").underlined(new JBColor(Gray._150, Gray._180));
+ painter.appendLine("No files are open");
- advertiseActions(splitters, painter);
+ if (!splitters.isPreview()) {
+ painter.underlined(new JBColor(Gray._150, Gray._180));
+ advertiseActions(splitters, painter);
+ }
painter.draw(g, new PairFunction<Integer, Integer, Couple<Integer>>() {
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
index 32169662ba2a..ddd5395805ff 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
@@ -287,7 +287,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme
}
}
- public FileEditorState getState(final VirtualFile file, final FileEditorProvider provider) {
+ public FileEditorState getState(@NotNull VirtualFile file, final FileEditorProvider provider) {
validateEntries();
final HistoryEntry entry = getEntry(file);
return entry != null ? entry.getState(provider) : null;
@@ -302,7 +302,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme
return entry != null ? entry.mySelectedProvider : null;
}
- private HistoryEntry getEntry(final VirtualFile file){
+ private HistoryEntry getEntry(@NotNull VirtualFile file){
validateEntries();
for (int i = myEntriesList.size() - 1; i >= 0; i--) {
final HistoryEntry entry = myEntriesList.get(i);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java
index babf76dd3709..58f5470aca07 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.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.
@@ -18,6 +18,7 @@ package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.extensions.ExtensionPointName;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -29,5 +30,5 @@ public interface EditorTabColorProvider {
ExtensionPointName<EditorTabColorProvider> EP_NAME = ExtensionPointName.create("com.intellij.editorTabColorProvider");
@Nullable
- Color getEditorTabColor(Project project, VirtualFile file);
+ Color getEditorTabColor(@NotNull Project project, @NotNull VirtualFile file);
}
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 03b03faffe03..3fa0f751e9cb 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
@@ -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.
@@ -381,7 +381,7 @@ public final class EditorTabbedContainer implements Disposable, CloseAction.Clos
}
@Nullable
- public static Color calcTabColor(final Project project, final VirtualFile file) {
+ public static Color calcTabColor(@NotNull Project project, @NotNull VirtualFile file) {
for (EditorTabColorProvider provider : Extensions.getExtensions(EditorTabColorProvider.EP_NAME)) {
final Color result = provider.getEditorTabColor(project, file);
if (result != null) {
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 06a3966ade1d..1bf86ea5d62c 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
@@ -287,7 +287,7 @@ public class EditorWindow {
}
}
- public void closeFile(final VirtualFile file, final boolean disposeIfNeeded, final boolean transferFocus) {
+ public void closeFile(@NotNull final VirtualFile file, final boolean disposeIfNeeded, final boolean transferFocus) {
final FileEditorManagerImpl editorManager = getManager();
editorManager.runChange(new FileEditorManagerChange() {
@Override
@@ -525,7 +525,7 @@ public class EditorWindow {
myOwner.setCurrentWindow(this, requestFocus);
}
- public void updateFileBackgroundColor(final VirtualFile file) {
+ public void updateFileBackgroundColor(@NotNull VirtualFile file) {
final int index = findEditorIndex(findFileComposite(file));
if (index != -1) {
final Color color = EditorTabbedContainer.calcTabColor(getManager().getProject(), file);
@@ -569,10 +569,10 @@ public class EditorWindow {
}
protected static class TComp extends JPanel implements DataProvider, EditorWindowHolder {
- final EditorWithProviderComposite myEditor;
+ @NotNull final EditorWithProviderComposite myEditor;
protected final EditorWindow myWindow;
- TComp(final EditorWindow window, final EditorWithProviderComposite editor) {
+ TComp(@NotNull EditorWindow window, @NotNull EditorWithProviderComposite editor) {
super(new BorderLayout());
myEditor = editor;
myWindow = window;
@@ -594,6 +594,7 @@ public class EditorWindow {
});
}
+ @NotNull
@Override
public EditorWindow getEditorWindow() {
return myWindow;
@@ -613,7 +614,7 @@ public class EditorWindow {
}
protected static class TCompForTablessMode extends TComp implements CloseAction.CloseTarget {
- TCompForTablessMode(final EditorWindow window, final EditorWithProviderComposite editor) {
+ TCompForTablessMode(@NotNull EditorWindow window, @NotNull EditorWithProviderComposite editor) {
super(window, editor);
}
@@ -701,6 +702,7 @@ public class EditorWindow {
public void setEditor(@Nullable final EditorWithProviderComposite editor, final boolean selectEditor, final boolean focusEditor) {
if (editor != null) {
+ onBeforeSetEditor(editor.getFile());
if (myTabbedPane == null) {
myPanel.removeAll ();
myPanel.add (new TCompForTablessMode(this, editor), BorderLayout.CENTER);
@@ -741,6 +743,9 @@ public class EditorWindow {
myOwner.validate();
}
+ protected void onBeforeSetEditor(VirtualFile file) {
+ }
+
private boolean splitAvailable() {
return getTabCount() >= 1;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java
index c708d058b63b..2d27bb853531 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.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.
@@ -15,9 +15,12 @@
*/
package com.intellij.openapi.fileEditor.impl;
+import org.jetbrains.annotations.NotNull;
+
/**
* @author Konstantin Bulenkov
*/
public interface EditorWindowHolder {
+ @NotNull
EditorWindow getEditorWindow();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
index b9e38809faab..c380d38a5db9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
@@ -51,6 +51,7 @@ import com.intellij.util.Alarm;
import com.intellij.util.containers.ArrayListSet;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
+import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -76,7 +77,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
private static final Key<Object> DUMMY_KEY = Key.create("EditorsSplitters.dummy.key");
- private final static EditorEmptyTextPainter ourPainter = ServiceManager.getService(EditorEmptyTextPainter.class);
+ private static final EditorEmptyTextPainter ourPainter = ServiceManager.getService(EditorEmptyTextPainter.class);
private EditorWindow myCurrentWindow;
final Set<EditorWindow> myWindows = new CopyOnWriteArraySet<EditorWindow>();
@@ -346,22 +347,18 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
return virtualFiles;
}
- @NotNull public FileEditor[] getSelectedEditors() {
- final List<FileEditor> editors = new ArrayList<FileEditor>();
+ @NotNull
+ public FileEditor[] getSelectedEditors() {
+ List<FileEditor> editors = new ArrayList<FileEditor>();
+ Set<EditorWindow> windows = new THashSet<EditorWindow>(myWindows);
final EditorWindow currentWindow = getCurrentWindow();
if (currentWindow != null) {
- final EditorWithProviderComposite composite = currentWindow.getSelectedEditor();
- if (composite != null) {
- editors.add (composite.getSelectedEditor());
- }
+ windows.add(currentWindow);
}
-
- for (final EditorWindow window : myWindows) {
- if (!window.equals(currentWindow)) {
- final EditorWithProviderComposite composite = window.getSelectedEditor();
- if (composite != null) {
- editors.add(composite.getSelectedEditor());
- }
+ for (final EditorWindow window : windows) {
+ final EditorWithProviderComposite composite = window.getSelectedEditor();
+ if (composite != null) {
+ editors.add(composite.getSelectedEditor());
}
}
return editors.toArray(new FileEditor[editors.size()]);
@@ -463,7 +460,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
myCurrentWindow = currentWindow;
}
- public void updateFileBackgroundColor(final VirtualFile file) {
+ public void updateFileBackgroundColor(@NotNull VirtualFile file) {
final EditorWindow[] windows = getWindows();
for (int i = 0; i != windows.length; ++ i) {
windows [i].updateFileBackgroundColor(file);
@@ -614,10 +611,14 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
public void createCurrentWindow() {
LOG.assertTrue(myCurrentWindow == null);
- setCurrentWindow(new EditorWindow(this));
+ setCurrentWindow(createEditorWindow());
add(myCurrentWindow.myPanel, BorderLayout.CENTER);
}
+ protected EditorWindow createEditorWindow() {
+ return new EditorWindow(this);
+ }
+
/**
* sets the window passed as a current ('focused') window among all splitters. All file openings will be done inside this
* current window
@@ -625,7 +626,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
* @param requestFocus whether to request focus to the editor currently selected in this window
*/
public void setCurrentWindow(@Nullable final EditorWindow window, final boolean requestFocus) {
- final EditorWithProviderComposite newEditor = window != null? window.getSelectedEditor() : null;
+ final EditorWithProviderComposite newEditor = window == null ? null : window.getSelectedEditor();
Runnable fireRunnable = new Runnable() {
@Override
@@ -655,7 +656,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
//---------------------------------------------------------
public EditorWithProviderComposite[] getEditorsComposites() {
- final ArrayList<EditorWithProviderComposite> res = new ArrayList<EditorWithProviderComposite>();
+ List<EditorWithProviderComposite> res = new ArrayList<EditorWithProviderComposite>();
for (final EditorWindow myWindow : myWindows) {
final EditorWithProviderComposite[] editors = myWindow.getEditors();
@@ -667,8 +668,8 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
//---------------------------------------------------------
@NotNull
- public List<EditorWithProviderComposite> findEditorComposites(final VirtualFile file) {
- final ArrayList<EditorWithProviderComposite> res = new ArrayList<EditorWithProviderComposite>();
+ public List<EditorWithProviderComposite> findEditorComposites(@NotNull VirtualFile file) {
+ List<EditorWithProviderComposite> res = new ArrayList<EditorWithProviderComposite>();
for (final EditorWindow window : myWindows) {
final EditorWithProviderComposite fileComposite = window.findFileComposite(file);
if (fileComposite != null) {
@@ -680,7 +681,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
@NotNull
public List<EditorWindow> findWindows(final VirtualFile file) {
- final ArrayList<EditorWindow> res = new ArrayList<EditorWindow>();
+ List<EditorWindow> res = new ArrayList<EditorWindow>();
for (final EditorWindow window : myWindows) {
if (window.findFileComposite(file) != null) {
res.add(window);
@@ -694,7 +695,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
}
@NotNull public EditorWindow[] getOrderedWindows() {
- final ArrayList<EditorWindow> res = new ArrayList<EditorWindow>();
+ final List<EditorWindow> res = new ArrayList<EditorWindow>();
// Collector for windows in tree ordering:
class Inner{
@@ -744,6 +745,10 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
return false;
}
+ public boolean isPreview() {
+ return false;
+ }
+
private final class MyFocusWatcher extends FocusWatcher {
@Override
protected void focusedComponentChanged(final Component component, final AWTEvent cause) {
@@ -816,8 +821,10 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
return processFiles(children, context);
}
- protected abstract @Nullable T processFiles(@NotNull List<Element> fileElements, @Nullable T context);
- protected abstract @Nullable T processSplitter(@NotNull Element element, @Nullable Element firstChild, @Nullable Element secondChild, @Nullable T context);
+ @Nullable
+ protected abstract T processFiles(@NotNull List<Element> fileElements, @Nullable T context);
+ @Nullable
+ protected abstract T processSplitter(@NotNull Element element, @Nullable Element firstChild, @Nullable Element secondChild, @Nullable T context);
}
private class UIBuilder extends ConfigTreeReader<JPanel> {
@@ -828,7 +835,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
- windowRef.set(context == null ? new EditorWindow(EditorsSplitters.this) : findWindowWith(context));
+ windowRef.set(context == null ? createEditorWindow() : findWindowWith(context));
}
});
final EditorWindow window = windowRef.get();
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 65adf52041b9..abf16d54c43d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -58,7 +58,6 @@ import com.intellij.openapi.vcs.FileStatusListener;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.wm.IdeFocusManager;
-import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
@@ -91,7 +90,6 @@ import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Anton Katilin
@@ -113,7 +111,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
private final Project myProject;
private final List<Pair<VirtualFile, EditorWindow>> mySelectionHistory = new ArrayList<Pair<VirtualFile, EditorWindow>>();
private WeakReference<EditorComposite> myLastSelectedComposite = new WeakReference<EditorComposite>(null);
- private final AtomicBoolean myPreviewBlocker = new AtomicBoolean(false);
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null);
@@ -179,9 +176,9 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
public Set<EditorsSplitters> getAllSplitters() {
HashSet<EditorsSplitters> all = new LinkedHashSet<EditorsSplitters>();
- if (Registry.is("editor.use.preview")) {
- initUI();
- all.add(myPreviewPanel.getWindow().getOwner());
+ EditorWindow previewWindow = getPreviewWindow();
+ if (previewWindow != null) {
+ all.add(previewWindow.getOwner());
}
all.add(getMainSplitters());
Set<DockContainer> dockContainers = myDockManager.getContainers();
@@ -255,16 +252,23 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
}
}
- if (myPreviewPanel == null && Registry.is("editor.use.preview")) {
+ if (myPreviewPanel == null && PreviewPanel.isAvailable()) {
synchronized (myInitLock) {
myPreviewPanel = new PreviewPanel(myProject, this, myDockManager);
}
}
}
+ @Nullable
+ private EditorWindow getPreviewWindow() {
+ if (!PreviewPanel.isAvailable()) return null;
+ initUI();
+ return myPreviewPanel.getWindow();
+ }
+
private static class MyBorder implements Border {
@Override
- public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+ public void paintBorder(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height) {
if (UIUtil.isUnderAquaLookAndFeel()) {
g.setColor(JBTabsImpl.MAC_AQUA_BG_COLOR);
final Insets insets = getBorderInsets(c);
@@ -274,6 +278,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
}
+ @NotNull
@Override
public Insets getBorderInsets(Component c) {
return JBInsets.NONE;
@@ -607,7 +612,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
@Override
@NotNull
public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull final VirtualFile file,
- final boolean focusEditor,
+ boolean focusEditor,
final boolean searchForSplitter) {
if (!file.isValid()) {
throw new IllegalArgumentException("file is not valid: " + file);
@@ -642,9 +647,10 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
if (wndToOpenIn == null || !wndToOpenIn.isFileOpen(file)) {
- EditorWindow previewWindow = getPreviewWindow(file, focusEditor, searchForSplitter);
+ EditorWindow previewWindow = getPreviewWindow();
if (previewWindow != null) {
wndToOpenIn = previewWindow;
+ focusEditor = true;
}
}
@@ -658,31 +664,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
return openFileImpl2(wndToOpenIn, file, focusEditor);
}
- @Nullable
- private EditorWindow getPreviewWindow(@NotNull VirtualFile virtualFile, final boolean focusEditor, final boolean searchForSplitter) {
- EditorWindow wndToOpenIn = null;
- if (Registry.is("editor.use.preview") && !myPreviewBlocker.get()) {
- wndToOpenIn = myPreviewPanel.getWindow();
- if (virtualFile.equals(myPreviewPanel.getCurrentFile())) return wndToOpenIn;
- final VirtualFile modifiedFile = myPreviewPanel.closeCurrentFile();
- ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).activate(null, false);
- if (modifiedFile != null) {
- CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
- @Override
- public void run() {
- myPreviewBlocker.set(true);
- try {
- openFileWithProviders(modifiedFile, focusEditor, searchForSplitter);
- } finally {
- myPreviewBlocker.set(false);
- }
- }
- }, "", null);
- }
- }
- return wndToOpenIn;
- }
-
public Pair<FileEditor[], FileEditorProvider[]> openFileInNewWindow(@NotNull VirtualFile file) {
return ((DockManagerImpl)DockManager.getInstance(getProject())).createNewDockContainerFor(file, this);
}
@@ -805,7 +786,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
final FileEditorProvider provider = newProviders[i];
LOG.assertTrue(provider != null, "Provider for file "+file+" is null. All providers: "+Arrays.asList(newProviders));
LOG.assertTrue(provider.accept(myProject, file), "Provider " + provider + " doesn't accept file " + file);
- if ((provider instanceof AsyncFileEditorProvider)) {
+ if (provider instanceof AsyncFileEditorProvider) {
builders[i] = ((AsyncFileEditorProvider)provider).createEditorAsync(myProject, file);
}
}
@@ -944,7 +925,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
return Pair.create(compositeRef.get().getEditors(), compositeRef.get().getProviders());
}
- private void clearWindowIfNeeded(EditorWindow window) {
+ private static void clearWindowIfNeeded(EditorWindow window) {
if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE || UISettings.getInstance().PRESENTATION_MODE) {
for (EditorWithProviderComposite composite : window.getEditors()) {
Disposer.dispose(composite);
@@ -1177,9 +1158,15 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
@Override
public Editor getSelectedTextEditor() {
- assertReadAccess();
+ return getSelectedTextEditor(false);
+ }
- final EditorWindow currentWindow = getSplitters().getCurrentWindow();
+ public Editor getSelectedTextEditor(boolean lockfree) {
+ if (!lockfree) {
+ assertDispatchThread();
+ }
+
+ final EditorWindow currentWindow = lockfree ? getMainSplitters().getCurrentWindow() : getSplitters().getCurrentWindow();
if (currentWindow != null) {
final EditorWithProviderComposite selectedEditor = currentWindow.getSelectedEditor();
if (selectedEditor != null && selectedEditor.getSelectedEditor() instanceof TextEditor) {
@@ -1191,6 +1178,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
+
@Override
public boolean isFileOpen(@NotNull final VirtualFile file) {
return !getEditorComposites(file).isEmpty();
@@ -1760,7 +1748,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
private final class MyEditorPropertyChangeListener implements PropertyChangeListener {
@Override
- public void propertyChange(final PropertyChangeEvent e) {
+ public void propertyChange(@NotNull final PropertyChangeEvent e) {
assertDispatchThread();
final String propertyName = e.getPropertyName();
@@ -1999,6 +1987,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
mySelectionHistory.remove(Pair.create(file, window));
}
+ @NotNull
@Override
public ActionCallback getReady(@NotNull Object requestor) {
return myBusyObject.getReady(requestor);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
index 752ab1228c3e..0e4f057dbeaf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java
@@ -145,16 +145,12 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
}
public static class RecentlyChangedFilesState {
- @Transient private List<String> CHANGED_PATHS = new ArrayList<String>();
+ @Transient private final List<String> CHANGED_PATHS = new ArrayList<String>();
public List<String> getChangedFiles() {
return CHANGED_PATHS;
}
- public void setChangedFiles(List<String> changed) {
- CHANGED_PATHS = changed;
- }
-
public void register(VirtualFile file) {
final String path = file.getPath();
CHANGED_PATHS.remove(path);
@@ -275,7 +271,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
myCurrentChangePlace = placeInfo;
if (!myChangePlaces.isEmpty()) {
- final PlaceInfo lastInfo = myChangePlaces.get(myChangePlaces.size() - 1);
+ final PlaceInfo lastInfo = myChangePlaces.getLast();
if (isSame(placeInfo, lastInfo)) {
myChangePlaces.removeLast();
}
@@ -430,7 +426,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
}
}
- private static boolean removeInvalidFilesFrom(final LinkedList<PlaceInfo> backPlaces) {
+ private static boolean removeInvalidFilesFrom(@NotNull List<PlaceInfo> backPlaces) {
boolean removed = false;
for (Iterator<PlaceInfo> iterator = backPlaces.iterator(); iterator.hasNext();) {
PlaceInfo info = iterator.next();
@@ -456,7 +452,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
myEditorManager.setSelectedEditor(info.getFile(), info.getEditorTypeId());
- final FileEditor [] editors = editorsWithProviders.getFirst();
+ final FileEditor[] editors = editorsWithProviders.getFirst();
final FileEditorProvider[] providers = editorsWithProviders.getSecond();
for (int i = 0; i < editors.length; i++) {
String typeId = providers [i].getEditorTypeId();
@@ -483,7 +479,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
return new PlaceInfo(file, state, fileProvider.getEditorTypeId(), myEditorManager.getCurrentWindow());
}
- private static void clearPlaceList(LinkedList<PlaceInfo> list) {
+ private static void clearPlaceList(@NotNull List<PlaceInfo> list) {
list.clear();
}
@@ -494,9 +490,9 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
return "IdeDocumentHistory";
}
- private static void putLastOrMerge(LinkedList<PlaceInfo> list, PlaceInfo next, int limitSizeLimit) {
+ private static void putLastOrMerge(@NotNull LinkedList<PlaceInfo> list, @NotNull PlaceInfo next, int limitSizeLimit) {
if (!list.isEmpty()) {
- PlaceInfo prev = list.get(list.size() - 1);
+ PlaceInfo prev = list.getLast();
if (isSame(prev, next)) {
list.removeLast();
}
@@ -522,7 +518,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
private final String myEditorTypeId;
private final WeakReference<EditorWindow> myWindow;
- public PlaceInfo(@NotNull VirtualFile file, FileEditorState navigationState, String editorTypeId, @Nullable EditorWindow window) {
+ public PlaceInfo(@NotNull VirtualFile file, @NotNull FileEditorState navigationState, @NotNull String editorTypeId, @Nullable EditorWindow window) {
myNavigationState = navigationState;
myFile = file;
myEditorTypeId = editorTypeId;
@@ -533,6 +529,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
return myWindow.get();
}
+ @NotNull
public FileEditorState getNavigationState() {
return myNavigationState;
}
@@ -542,24 +539,23 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
return myFile;
}
+ @NotNull
public String getEditorTypeId() {
return myEditorTypeId;
}
+ @Override
public String toString() {
return getFile().getName() + " " + getNavigationState();
}
}
- public LinkedList<PlaceInfo> getBackPlaces() {
+ @NotNull
+ public List<PlaceInfo> getBackPlaces() {
return myBackPlaces;
}
- public LinkedList<PlaceInfo> getForwardPlaces() {
- return myForwardPlaces;
- }
-
@Override
public final void initComponent() { }
@@ -572,7 +568,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec
myCmdProcessor.executeCommand(myProject, runnable, name, groupId);
}
- private static boolean isSame(PlaceInfo first, PlaceInfo second) {
+ private static boolean isSame(@NotNull PlaceInfo first, @NotNull PlaceInfo second) {
if (first.getFile().equals(second.getFile())) {
FileEditorState firstState = first.getNavigationState();
FileEditorState secondState = second.getNavigationState();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java
index a9634d5a335a..999fe75523e9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java
@@ -17,162 +17,276 @@ package com.intellij.openapi.fileEditor.impl;
import com.intellij.icons.AllIcons;
import com.intellij.ide.ui.UISettings;
+import com.intellij.ide.ui.UISettingsListener;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.editor.event.DocumentListener;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.ToolWindowAnchor;
-import com.intellij.openapi.wm.ToolWindowId;
-import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
-import com.intellij.ui.JBColor;
+import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentManager;
+import com.intellij.ui.content.ContentManagerAdapter;
+import com.intellij.ui.content.ContentManagerEvent;
import com.intellij.ui.docking.DockManager;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
+import java.util.EnumSet;
-class PreviewPanel extends JPanel implements DocumentListener, FileEditorManagerListener.Before {
+class PreviewPanel extends JPanel {
+
+ private CardLayout myLayout;
+
+ enum ContentType {Files, Usages, Diagrams, Documentation}
+
+ private static final Key<VirtualFile> FILE_KEY = Key.create("v_file");
private static final int HISTORY_LIMIT = 10;
private final Project myProject;
private final FileEditorManagerImpl myManager;
private final DockManager myDockManager;
private EditorWindow myWindow;
- private boolean myInitialized = false;
private EditorsSplitters myEditorsSplitters;
private ArrayList<VirtualFile> myHistory = new ArrayList<VirtualFile>();
private VirtualFile myModifiedFile = null;
private ToolWindowImpl myToolWindow;
private VirtualFile myAwaitingForOpen = null;
+ private ContentManager myContentManager;
+ private Content myStubContent;
+ private boolean myBlocked = false;
+
+ private EnumSet<ContentType> myTypes = EnumSet.noneOf(ContentType.class);
+
+ static boolean isAvailable() {
+ return UISettings.getInstance().NAVIGATE_TO_PREVIEW;
+ }
- public PreviewPanel(Project project, FileEditorManagerImpl manager, DockManager dockManager) {
+ PreviewPanel(Project project, FileEditorManagerImpl manager, DockManager dockManager) {
myProject = project;
myManager = manager;
myDockManager = dockManager;
- setOpaque(true);
- setBackground(JBColor.DARK_GRAY);
+ }
+
+ /*
+ * @return null if preview is not avalable
+ */
+ @Nullable
+ EditorWindow getWindow() {
+ if (!isAvailable() || isBlocked() || myProject.isDisposed()) return null;
+ initToolWindowIfNeed();
+ return myWindow;
+ }
+
+ boolean isBlocked() {
+ return myBlocked;
}
private void initToolWindowIfNeed() {
- if (myInitialized) return;
+ if (!isAvailable() || ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW) != null) return;
myToolWindow = (ToolWindowImpl)ToolWindowManager.getInstance(myProject)
.registerToolWindow(ToolWindowId.PREVIEW, this, ToolWindowAnchor.RIGHT, myProject, false);
- myToolWindow.setIcon(AllIcons.Actions.PreviewDetails);
-
- myEditorsSplitters = new EditorsSplitters(myManager, myDockManager, false) {
+ UISettings.getInstance().addUISettingsListener(new UISettingsListener() {
@Override
- public void updateFileName(VirtualFile updatedFile) {
- super.updateFileName(updatedFile);
- if (updatedFile != null && updatedFile.equals(getCurrentFile())) {
- updateWindowTitle(updatedFile);
- }
- }
-
- @Override
- protected void afterFileOpen(VirtualFile file) {
- if (file.equals(myAwaitingForOpen)) {
- updateWindowTitle(file);
- Document document = FileDocumentManager.getInstance().getDocument(file);
- if (document != null) {
- myModifiedFile = null;
- document.addDocumentListener(PreviewPanel.this, myProject);
+ public void uiSettingsChanged(UISettings source) {
+ if (!isAvailable()) {
+ VirtualFile[] files = myWindow.getFiles();
+ for (VirtualFile file : files) {
+ close(file);
}
+ ToolWindowManager.getInstance(myProject).unregisterToolWindow(ToolWindowId.PREVIEW);
}
- myAwaitingForOpen = null;
}
-
+ }, myProject);
+ myToolWindow.setIcon(AllIcons.Actions.PreviewDetails);
+ myToolWindow.setContentUiType(ToolWindowContentUiType.COMBO, null);
+ myContentManager = myToolWindow.getContentManager();
+ myStubContent = myContentManager.getContent(0);
+ myContentManager.addContentManagerListener(new ContentManagerAdapter() {
@Override
- public void setTabsPlacement(int tabPlacement) {
- super.setTabsPlacement(UISettings.TABS_NONE);
- }
+ public void selectionChanged(ContentManagerEvent event) {
+ final VirtualFile file = event.getContent().getUserData(FILE_KEY);
+ if (event.getOperation() == ContentManagerEvent.ContentOperation.remove && file != null && file.equals(myModifiedFile)) {
+ close(file);
+ return;
+ }
- @Override
- protected boolean showEmptyText() {
- return false;
+ if (event.getOperation() != ContentManagerEvent.ContentOperation.add) return;
+
+ if (file != null) {
+ event.getContent().setComponent(PreviewPanel.this);//Actually we share the same component between contents
+ if (!file.equals(myWindow.getSelectedFile())) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ myManager.openFileWithProviders(file, false, myWindow);
+ }
+ });
+ }
+ }
}
- };
-
- myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER, this);
+ });
+
+ myEditorsSplitters = new MyEditorsSplitters();
+
+ myProject.getMessageBus().connect().subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER,
+ new FileEditorManagerListener.Before() {
+ @Override
+ public void beforeFileOpened(@NotNull FileEditorManager source,
+ @NotNull VirtualFile file) {
+ myAwaitingForOpen = file;
+ VirtualFile currentFile = getCurrentFile();
+ if (currentFile != null &&
+ currentFile.equals(myModifiedFile) &&
+ !currentFile.equals(file)) {
+ close(currentFile);
+ }
+ }
+
+ @Override
+ public void beforeFileClosed(@NotNull FileEditorManager source,
+ @NotNull VirtualFile file) {
+ checkStubContent();
+ }
+ });
myEditorsSplitters.createCurrentWindow();
-
myWindow = myEditorsSplitters.getCurrentWindow();
myWindow.setTabsPlacement(UISettings.TABS_NONE);
+ myLayout = new CardLayout();
+ setLayout(myLayout);
+ add(ContentType.Files.toString(), myEditorsSplitters);
+ //add(ContentType.Usages.toString(), myUsagesPreview);??? tree or editor ???
+ //add(ContentType.Diagrams.toString(), myDiagramPanel);
+ //add(ContentType.Documentation.toString(), myDocumentationPanel);//todo
+ myToolWindow.setTitleActions(new MoveToEditorTabsAction());
+ ArrayList<AnAction> myGearActions = new ArrayList<AnAction>();
+ for (ContentType contentType : ContentType.values()) {
+ myGearActions.add(new ContentTypeToggleAction(contentType));
+ }
+ myToolWindow.setAdditionalGearActions(new DefaultActionGroup("Preview", myGearActions));
+ myToolWindow.hide(null);
+ }
- setLayout(new GridLayout(1, 1));
- add(myEditorsSplitters);
-
- myToolWindow.setTitleActions(new MoveToEditorTabsAction(), new CloseFileAction());
-
- myInitialized = true;
+ @Nullable
+ private VirtualFile getCurrentFile() {
+ VirtualFile[] files = myWindow.getFiles();
+ return files.length == 1 ? files[0] : null;
}
- private void updateWindowTitle(VirtualFile file) {
- if (myToolWindow == null) return;
- if (file == null) {
- myToolWindow.setTitle(": (empty)");
- }
- else {
- myToolWindow.setTitle(": " +
- StringUtil.getShortened(EditorTabbedContainer.calcTabTitle(myProject, file),
- UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT));
+ @NotNull
+ private Content addContent(VirtualFile file) {
+ myHistory.add(file);
+ while (myHistory.size() > HISTORY_LIMIT) {
+ myHistory.remove(0);
}
+ String title =
+ StringUtil.getShortened(EditorTabbedContainer.calcTabTitle(myProject, file), UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT);
+
+ Content content = myContentManager.getFactory().createContent(this, title, false);
+ content.putUserData(ToolWindow.SHOW_CONTENT_ICON, Boolean.TRUE);
+ content.putUserData(FILE_KEY, file);
+ content.setIcon(file.getFileType().getIcon());
+ content.setPopupIcon(file.getFileType().getIcon());
+
+ myContentManager.addContent(content, 0);
+ checkStubContent();
+ return content;
}
- @Override
- public void beforeFileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
- myAwaitingForOpen = file;
+ private void setSelected(VirtualFile file) {
+ Content content = getContent(file);
+ if (content == null) {
+ content = addContent(file);
+ }
+ myContentManager.setSelectedContent(content);
+ myContentManager.addContent(content, 0);
}
- @Override
- public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
- if (file.equals(getCurrentFile())) {
- updateWindowTitle(null);
- Document document = FileDocumentManager.getInstance().getDocument(file);
- if (document != null) {
- document.removeDocumentListener(this);
+ @Nullable
+ private Content getContent(VirtualFile file) {
+ Content[] contents = myContentManager.getContents();
+ for (Content content : contents) {
+ if (file.equals(content.getUserData(FILE_KEY))) {
+ return content;
}
}
+ return null;
}
-
- @Override
- public void beforeDocumentChange(DocumentEvent event) {
-
- }
-
- @Override
- public void documentChanged(DocumentEvent event) {
- VirtualFile file = FileDocumentManager.getInstance().getFile(event.getDocument());
- if (file != null) {
- myModifiedFile = file;
+ private void checkStubContent() {
+ if (myContentManager.getContents().length == 0) {
+ myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "false");
+ myStubContent.setComponent(this);
+ myContentManager.addContent(myStubContent);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (myContentManager.getIndexOfContent(myStubContent) != -1) {
+ toggleToolWindow(false);
+ }
+ }
+ });
+ }
+ else if (myContentManager.getContents().length > 1) {
+ myToolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
+ myContentManager.removeContent(myStubContent, false);
}
}
- EditorWindow getWindow() {
- initToolWindowIfNeed();
- return myWindow;
+ private void close(@NotNull VirtualFile file) {
+ myHistory.remove(file);
+ if (ArrayUtil.find(myEditorsSplitters.getOpenFiles(), file) != -1) {
+ myEditorsSplitters.closeFile(file, false);
+ }
+ if (file.equals(myAwaitingForOpen)) {
+ myAwaitingForOpen = null;
+ }
+ if (file.equals(myModifiedFile)) {
+ myBlocked = true;
+ try {
+ myManager.openFileWithProviders(myModifiedFile, false, true);
+ }
+ finally {
+ myBlocked = false;
+ }
+ myModifiedFile = null;
+ }
+ Content content = getContent(file);
+ if (content != null) {
+ myContentManager.removeContent(content, false);
+ checkStubContent();
+ }
}
- @Nullable
- VirtualFile getCurrentFile() {
- VirtualFile[] files = myWindow.getFiles();
- return files.length == 1 ? files[0] : null;
+ private void toggleToolWindow(boolean activate) {
+ ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW);
+ if (toolWindow != null) {
+ if (activate) {
+ toolWindow.activate(null, false);
+ }
+ else {
+ toolWindow.hide(null);
+ }
+ }
}
private class MoveToEditorTabsAction extends AnAction {
+
public MoveToEditorTabsAction() {
- super(null, "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed);
+ super("Move to main tabs", "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed);
}
@Override
@@ -182,63 +296,96 @@ class PreviewPanel extends JPanel implements DocumentListener, FileEditorManager
return;
}
- myManager.openFileWithProviders(virtualFile, false, myManager.getCurrentWindow());
- closeCurrentFile();
+ EditorWindow window = myManager.getCurrentWindow();
+ if (window == null) { //main tab set is still not created, rare situation
+ myManager.getMainSplitters().createCurrentWindow();
+ window = myManager.getCurrentWindow();
+ }
+ myManager.openFileWithProviders(virtualFile, true, window);
+ close(virtualFile);
+ toggleToolWindow(false);
+ }
+ }
+
+ private class ContentTypeToggleAction extends ToggleAction {
+ private final ContentType myContentType;
+
+ ContentTypeToggleAction(ContentType contentType) {
+ super(contentType.toString());
+ myContentType = contentType;
}
@Override
- public void update(AnActionEvent e) {
- super.update(e);
- VirtualFile currentFile = getCurrentFile();
- e.getPresentation().setEnabled(currentFile != null);
- if (currentFile == null) return;
-
- if (isModified(currentFile)) {
- e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeft);
- }
- else {
- e.getPresentation().setIcon(AllIcons.Duplicates.SendToTheLeftGrayed);
+ public boolean isSelected(AnActionEvent e) {
+ return myTypes.contains(myContentType);
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ if (state) {
+ myTypes.add(myContentType);
+ } else {
+ myTypes.remove(myContentType);
}
}
}
- private boolean isModified(@NotNull VirtualFile file) {
- return file.equals(myModifiedFile);
- }
+ private class MyEditorsSplitters extends EditorsSplitters {
+ public MyEditorsSplitters() {
+ super(myManager, myDockManager, false);
+ }
- //returns last open file if it has "modified" status
- @Nullable
- VirtualFile closeCurrentFile() {
- VirtualFile virtualFile = getCurrentFile();
- if (virtualFile == null) return null;
- if (!myHistory.contains(virtualFile)) {
- myHistory.add(virtualFile);
- while (myHistory.size() > HISTORY_LIMIT) {
- myHistory.remove(0);
+ @Override
+ protected void afterFileOpen(VirtualFile file) {
+ if (file.equals(myAwaitingForOpen)) {
+ setSelected(file);
}
+ myAwaitingForOpen = null;
+ }
+
+ @Override
+ protected void afterFileClosed(VirtualFile file) {
+ close(file);
}
- myWindow.closeFile(virtualFile);
- this.revalidate();
- this.repaint();
- return isModified(virtualFile) ? virtualFile : null;
- }
- private class CloseFileAction extends AnAction {
- public CloseFileAction() {
- super(null, "Close", AllIcons.Actions.Close);
+ @Override
+ public void updateFileIcon(@NotNull VirtualFile file) {
+ EditorWithProviderComposite composite = myWindow.findFileComposite(file);
+ if (composite != null && composite.isModified()) {
+ myModifiedFile = file;
+ }
}
@Override
- public void actionPerformed(AnActionEvent e) {
- if (getCurrentFile() == null) return;
- closeCurrentFile();
- ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).hide(null);
+ protected EditorWindow createEditorWindow() {
+ return new EditorWindow(this) {
+ @Override
+ protected void onBeforeSetEditor(VirtualFile file) {
+ VirtualFile currentFile = getCurrentFile();
+ if (currentFile != null && currentFile.equals(myModifiedFile)) {
+ myBlocked = true;
+ try {
+ myManager.openFileWithProviders(myModifiedFile, false, true);
+ }
+ finally {
+ myBlocked = false;
+ }
+ }
+ else {
+ toggleToolWindow(true);
+ }
+ }
+ };
+ }
+
+ @Override
+ public void setTabsPlacement(int tabPlacement) {
+ super.setTabsPlacement(UISettings.TABS_NONE);
}
@Override
- public void update(AnActionEvent e) {
- super.update(e);
- e.getPresentation().setEnabled(getCurrentFile() != null);
+ public boolean isPreview() {
+ return true;
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
index 00f333ef4002..a676023b6590 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.BaseRemoteFileEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
+import com.intellij.openapi.vfs.impl.http.RemoteFileInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,14 +29,16 @@ import javax.swing.*;
/**
* @author nik
*/
-public class HttpFileEditor extends BaseRemoteFileEditor {
+class HttpFileEditor extends BaseRemoteFileEditor {
private final RemoteFilePanel myPanel;
public HttpFileEditor(@NotNull Project project, @NotNull HttpVirtualFile virtualFile) {
super(project);
myPanel = new RemoteFilePanel(project, virtualFile, this);
- virtualFile.getFileInfo().download().doWhenDone(new Runnable() {
+ RemoteFileInfo fileInfo = virtualFile.getFileInfo();
+ assert fileInfo != null;
+ fileInfo.download().doWhenDone(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
index 17354c7f4855..22234ab66a74 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditorProvider.java
@@ -31,7 +31,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
-public class HttpFileEditorProvider implements FileEditorProvider, DumbAware {
+class HttpFileEditorProvider implements FileEditorProvider, DumbAware {
@Override
public boolean accept(@NotNull final Project project, @NotNull final VirtualFile file) {
return file instanceof HttpVirtualFile && !file.isDirectory();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
index 076d29e64bbe..4bd5549d85ff 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/RemoteFilePanel.java
@@ -83,6 +83,7 @@ public class RemoteFilePanel {
final RemoteFileInfo remoteFileInfo = virtualFile.getFileInfo();
myDownloadingListener = new MyDownloadingListener();
+ assert remoteFileInfo != null;
remoteFileInfo.addDownloadingListener(myDownloadingListener);
myCancelButton.addActionListener(new ActionListener() {
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
index 837626b53246..01d278302540 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
@@ -209,7 +209,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
}
@Override
- public Document writeScheme(@NotNull final AbstractFileType fileType) throws WriteExternalException {
+ public Element writeScheme(@NotNull final AbstractFileType fileType) throws WriteExternalException {
Element root = new Element(ELEMENT_FILETYPE);
writeHeader(root, fileType);
@@ -226,7 +226,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
writeExtensionsMap(map, fileType, false);
}
- return new Document(root);
+ return root;
}
@Override
@@ -263,7 +263,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
});
}
- private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("File type re-detect", Condition.FALSE, -1, new Processor<Collection<VirtualFile>>() {
+ private final TransferToPooledThreadQueue<Collection<VirtualFile>> reDetectQueue = new TransferToPooledThreadQueue<Collection<VirtualFile>>("File type re-detect", Conditions.alwaysFalse(), -1, new Processor<Collection<VirtualFile>>() {
@Override
public boolean process(Collection<VirtualFile> files) {
reDetect(files);
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
index 9a566e9915ef..72e24d626535 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java
@@ -55,6 +55,7 @@ import com.intellij.ui.ComponentWithMnemonics;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.components.JBOptionButton;
import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.ui.speedSearch.SpeedSearchSupply;
import com.intellij.util.Alarm;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
@@ -140,6 +141,10 @@ public final class IdeKeyEventDispatcher implements Disposable {
return false;
}
+ if (isSpeedSearchEditing(e)) {
+ return false;
+ }
+
// http://www.jetbrains.net/jira/browse/IDEADEV-12372
if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
@@ -226,6 +231,18 @@ public final class IdeKeyEventDispatcher implements Disposable {
}
}
+ private static boolean isSpeedSearchEditing(KeyEvent e) {
+ int keyCode = e.getKeyCode();
+ if (keyCode == KeyEvent.VK_BACK_SPACE) {
+ Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if (owner instanceof JComponent) {
+ SpeedSearchSupply supply = SpeedSearchSupply.getSupply((JComponent)owner);
+ return supply != null && supply.isPopupActive();
+ }
+ }
+ return false;
+ }
+
/**
* @return <code>true</code> if and only if the <code>component</code> represents
* modal context.
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 7c30e4faedec..177aa4babad1 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
@@ -44,11 +44,7 @@ import java.util.*;
@State(
name = "KeymapManager",
- roamingType = RoamingType.PER_PLATFORM,
- storages = {
- @Storage(
- file = StoragePathMacros.APP_CONFIG + "/keymap.xml"
- )}
+ storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/keymap.xml", roamingType = RoamingType.PER_PLATFORM)}
)
public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStateComponent<Element>, ExportableApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.keymap.KeymapManager");
@@ -75,8 +71,8 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat
}
@Override
- public Document writeScheme(@NotNull final KeymapImpl scheme) throws WriteExternalException {
- return new Document(scheme.writeExternal());
+ public Element writeScheme(@NotNull final KeymapImpl scheme) throws WriteExternalException {
+ return scheme.writeExternal();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
index 449a2180e3c1..c2f3b4d72b3e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
@@ -28,8 +28,6 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
public class SchemesManagerFactoryImpl extends SchemesManagerFactory implements SettingsSavingComponent {
@@ -47,63 +45,10 @@ public class SchemesManagerFactoryImpl extends SchemesManagerFactory implements
}
IApplicationStore applicationStore = ((ApplicationImpl)application).getStateStore();
String baseDirPath = applicationStore.getStateStorageManager().expandMacros(fileSpec);
- if (baseDirPath != null) {
- StreamProvider provider = applicationStore.getStateStorageManager().getStreamProvider();
- SchemesManagerImpl<T, E> manager = new SchemesManagerImpl<T, E>(fileSpec, processor, roamingType, provider, new File(baseDirPath));
- myRegisteredManagers.add(manager);
- return manager;
- }
- else {
- return new AbstractSchemesManager<T, E>() {
- @Override
- @NotNull
- public Collection<E> loadSchemes() {
- return Collections.emptyList();
- }
-
- @Override
- @NotNull
- public Collection<SharedScheme<E>> loadSharedSchemes(final Collection<T> currentSchemeList) {
- return Collections.emptyList();
- }
-
- @Override
- public void exportScheme(@NotNull final E scheme, final String name, final String description) {
- }
-
- @Override
- public boolean isImportAvailable() {
- return false;
- }
-
- @Override
- public boolean isShared(final Scheme scheme) {
- return false;
- }
-
- @Override
- public void save() {
- }
-
- @Override
- protected void onSchemeDeleted(final Scheme toDelete) {
- }
-
- @Override
- protected void onSchemeAdded(final T scheme) {
- }
-
- @Override
- public boolean isExportAvailable() {
- return false;
- }
-
- @Override
- public File getRootDirectory() {
- return null;
- }
- };
- }
+ StreamProvider provider = applicationStore.getStateStorageManager().getStreamProvider();
+ SchemesManagerImpl<T, E> manager = new SchemesManagerImpl<T, E>(fileSpec, processor, roamingType, provider, new File(baseDirPath));
+ myRegisteredManagers.add(manager);
+ return manager;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
index 4ff3ebba1ee9..6142b696ff24 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
@@ -43,6 +43,7 @@ import gnu.trove.THashSet;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
+import org.jdom.Parent;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -79,7 +80,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
private boolean myListenerAdded = false;
private Alarm myRefreshAlarm;
-
+
private String mySchemeExtension = DEFAULT_EXT;
private boolean myUpgradeExtension = false;
@@ -535,7 +536,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
@Nullable
private static Document loadGlobalScheme(final String schemePath) throws IOException {
StreamProvider provider = getProvider();
- return provider != null && provider.isEnabled() ? StorageUtil.loadDocument(provider.loadContent(schemePath, RoamingType.GLOBAL)) : null;
+ return provider != null && provider.isEnabled() ? StorageUtil.loadDocument(provider.loadContent(schemePath, getRoamingType(provider))) : null;
}
private void saveFileName(String fileName, final E schemeKey) {
@@ -548,12 +549,12 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
schemeKey.getExternalInfo().setCurrentFileName(fileName);
}
- private static long computeHashValue(final Document document) {
- return JDOMUtil.getTreeHash(document);
+ private static long computeHashValue(Parent element) {
+ return JDOMUtil.getTreeHash(element instanceof Element ? (Element)element : ((Document)element).getRootElement());
}
@Nullable
- private Document writeSchemeToDocument(final E scheme) throws WriteExternalException {
+ private org.jdom.Parent writeSchemeToDocument(@NotNull E scheme) throws WriteExternalException {
if (isShared(scheme)) {
String originalPath = scheme.getExternalInfo().getOriginalPath();
if (originalPath != null) {
@@ -562,11 +563,10 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
root.setAttribute(ORIGINAL_SCHEME_PATH, originalPath);
Element localCopy = new Element(SCHEME_LOCAL_COPY);
- localCopy.addContent(myProcessor.writeScheme(scheme).getRootElement().clone());
+ localCopy.addContent(getClone(myProcessor.writeScheme(scheme)));
root.addContent(localCopy);
-
- return new Document(root);
+ return root;
}
else {
return null;
@@ -577,8 +577,12 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
- public void updateConfigFilesFromStreamProviders() {
+ @NotNull
+ private static Element getClone(@NotNull Parent result) {
+ return (result instanceof Element ? (Element)result : ((Document)result).getRootElement()).clone();
+ }
+ public void updateConfigFilesFromStreamProviders() {
}
private static class SharedSchemeData {
@@ -605,9 +609,9 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
Collection<String> names = new THashSet<String>(getAllSchemeNames(currentSchemeList));
Map<String, SharedScheme<E>> result = new THashMap<String, SharedScheme<E>>();
- for (String subPath : provider.listSubFiles(myFileSpec, RoamingType.GLOBAL)) {
+ for (String subPath : provider.listSubFiles(myFileSpec, getRoamingType(provider))) {
try {
- final Document subDocument = StorageUtil.loadDocument(provider.loadContent(getFileFullPath(subPath), RoamingType.GLOBAL));
+ final Document subDocument = StorageUtil.loadDocument(provider.loadContent(getFileFullPath(subPath), getRoamingType(provider)));
if (subDocument != null) {
SharedSchemeData original = unwrap(subDocument);
final E scheme = myProcessor.readScheme(original.original);
@@ -669,6 +673,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return myFileSpec + '/' + subPath;
}
+ @SuppressWarnings("deprecation")
@Override
public void exportScheme(@NotNull final E scheme, final String name, final String description) throws WriteExternalException, IOException {
StreamProvider provider = getProvider();
@@ -676,31 +681,39 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return;
}
- Document document = myProcessor.writeScheme(scheme);
+ Parent document = myProcessor.writeScheme(scheme);
if (document != null) {
String fileSpec = getFileFullPath(UniqueFileNamesProvider.convertName(scheme.getName())) + mySchemeExtension;
- if (!provider.isApplicable(fileSpec, RoamingType.GLOBAL)) {
+ if (!provider.isApplicable(fileSpec, getRoamingType(provider))) {
return;
}
- Document wrapped = wrap(document, name, description);
+ Element wrapped = wrap(document, name, description);
if (provider instanceof CurrentUserHolder) {
wrapped = wrapped.clone();
String userName = ((CurrentUserHolder)provider).getCurrentUserName();
if (userName != null) {
- wrapped.getRootElement().setAttribute(USER, userName);
+ wrapped.setAttribute(USER, userName);
}
}
- StorageUtil.doSendContent(provider, fileSpec, wrapped, RoamingType.GLOBAL, false);
+ StorageUtil.doSendContent(provider, fileSpec, wrapped, getRoamingType(provider), false);
}
}
- private static Document wrap(@NotNull Document original, @NotNull String name, @NotNull String description) {
+ @SuppressWarnings("deprecation")
+ @NotNull
+ private static RoamingType getRoamingType(@NotNull StreamProvider provider) {
+ // for deprecated old stream we use GLOBAL as before to preserve backward compatibility
+ return provider instanceof CurrentUserHolder ? RoamingType.GLOBAL : RoamingType.PER_USER;
+ }
+
+ @NotNull
+ private static Element wrap(@NotNull Parent original, @NotNull String name, @NotNull String description) {
Element sharedElement = new Element(SHARED_SCHEME_ORIGINAL);
sharedElement.setAttribute(NAME, name);
sharedElement.setAttribute(DESCRIPTION, description);
- sharedElement.addContent(original.getRootElement().clone());
- return new Document(sharedElement);
+ sharedElement.addContent(getClone(original));
+ return sharedElement;
}
@Override
@@ -799,7 +812,7 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
deleteServerFiles(DELETED_XML);
}
else if (myProvider != null && myProvider.isEnabled()) {
- StorageUtil.sendContent(myProvider, getFileFullPath(DELETED_XML), createDeletedDocument(), myRoamingType, true);
+ StorageUtil.sendContent(myProvider, getFileFullPath(DELETED_XML), createDeletedElement(), myRoamingType, true);
}
}
finally {
@@ -850,11 +863,11 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
final String fileName = getFileNameForScheme(fileNameProvider, eScheme);
try {
- final Document document = writeSchemeToDocument(eScheme);
- if (document != null) {
- long newHash = computeHashValue(document);
+ final Parent element = writeSchemeToDocument(eScheme);
+ if (element != null) {
+ long newHash = computeHashValue(element);
Long oldHash = eScheme.getExternalInfo().getHash();
- saveIfNeeded(eScheme, fileName, document, newHash, oldHash);
+ saveIfNeeded(eScheme, fileName, element, newHash, oldHash);
}
}
catch (final IOException e) {
@@ -889,18 +902,18 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
return fileName + mySchemeExtension;
}
- private void saveIfNeeded(E schemeKey, String fileName, Document document, long newHash, Long oldHash) throws IOException {
+ private void saveIfNeeded(E schemeKey, String fileName, Parent element, long newHash, Long oldHash) throws IOException {
if (oldHash == null || newHash != oldHash.longValue() || myVFSBaseDir.findChild(fileName) == null) {
- ensureFileText(fileName, StorageUtil.documentToBytes(document, true).toByteArray());
+ ensureFileText(fileName, StorageUtil.elementToBytes(element, true).toByteArray());
schemeKey.getExternalInfo().setHash(newHash);
saveFileName(fileName, schemeKey);
- saveOnServer(fileName, document);
+ saveOnServer(fileName, element);
}
}
- private void saveOnServer(final String fileName, final Document document) {
+ private void saveOnServer(final String fileName, @NotNull Parent element) {
if (myProvider != null && myProvider.isEnabled()) {
- StorageUtil.sendContent(myProvider, getFileFullPath(fileName), document, myRoamingType, true);
+ StorageUtil.sendContent(myProvider, getFileFullPath(fileName), element, myRoamingType, true);
}
}
@@ -925,16 +938,15 @@ public class SchemesManagerImpl<T extends Scheme, E extends ExternalizableScheme
}
}
- private Document createDeletedDocument() {
+ @NotNull
+ private Element createDeletedElement() {
Element root = new Element("deleted-schemes");
- Document result = new Document(root);
for (String deletedName : myDeletedNames) {
Element child = new Element("scheme");
root.addContent(child);
child.setAttribute("name", deletedName);
}
-
- return result;
+ return root;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
index 429a55b2b809..ca72bf30c541 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
@@ -48,7 +48,7 @@ public class ConfigurableExtensionPointUtil {
}
}
- final Map<String, ConfigurableWrapper> idToConfigurable = new HashMap<String, ConfigurableWrapper>();
+ final Map<String, ConfigurableWrapper> idToConfigurable = new LinkedHashMap<String, ConfigurableWrapper>();
for (ConfigurableEP<Configurable> ep : extensions) {
final Configurable configurable = ConfigurableWrapper.wrapConfigurable(ep);
if (isSuppressed(configurable, filter)) continue;
@@ -75,16 +75,13 @@ public class ConfigurableExtensionPointUtil {
}
}
}
- //leave only roots (i.e. configurables without parents)
- for (final Iterator<String> iterator = idToConfigurable.keySet().iterator(); iterator.hasNext(); ) {
- final String key = iterator.next();
- final ConfigurableWrapper wrapper = idToConfigurable.get(key);
- final String parentId = wrapper.getParentId();
- if (parentId != null && idToConfigurable.containsKey(parentId)) {
- iterator.remove(); // remove only processed parents
+ // add roots only (i.e. configurables without parents)
+ for (ConfigurableWrapper wrapper : idToConfigurable.values()) {
+ String parentId = wrapper.getParentId();
+ if (parentId == null || !idToConfigurable.containsKey(parentId)) {
+ result.add(wrapper);
}
}
- ContainerUtil.addAll(result, idToConfigurable.values());
return result;
}
@@ -164,7 +161,7 @@ public class ConfigurableExtensionPointUtil {
@NotNull
private static <T extends Configurable> T findConfigurable(ConfigurableEP<Configurable>[] extensions, Class<T> configurableClass) {
for (ConfigurableEP<Configurable> extension : extensions) {
- if (extension.providerClass != null || extension.instanceClass != null || extension.implementationClass != null) {
+ if (extension.canCreateConfigurable()) {
final Configurable configurable = extension.createConfigurable();
if (configurableClass.isInstance(configurable)) {
return configurableClass.cast(configurable);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java
new file mode 100644
index 000000000000..7d820a255fb3
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableVisitor.java
@@ -0,0 +1,144 @@
+/*
+ * 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.ex;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurableGroup;
+import com.intellij.openapi.options.SearchableConfigurable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Sergey.Malenkov
+ */
+public abstract class ConfigurableVisitor {
+ public static final ConfigurableVisitor ALL = new ConfigurableVisitor() {
+ @Override
+ protected boolean accept(Configurable configurable) {
+ return true;
+ }
+ };
+
+ protected abstract boolean accept(Configurable configurable);
+
+ public final Configurable find(@NotNull ConfigurableGroup... groups) {
+ for (ConfigurableGroup group : groups) {
+ Configurable result = find(group.getConfigurables());
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ public final Configurable find(@NotNull Configurable... configurables) {
+ for (Configurable configurable : configurables) {
+ if (accept(configurable)) {
+ return configurable;
+ }
+ }
+ for (Configurable configurable : configurables) {
+ if (configurable instanceof Configurable.Composite) {
+ Configurable.Composite composite = (Configurable.Composite)configurable;
+ Configurable result = find(composite.getConfigurables());
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+
+ public final List<Configurable> findAll(@NotNull ConfigurableGroup... groups) {
+ List<Configurable> list = new ArrayList<Configurable>();
+ for (ConfigurableGroup group : groups) {
+ add(list, group.getConfigurables());
+ }
+ return list;
+ }
+
+ public final List<Configurable> findAll(@NotNull Configurable... configurables) {
+ List<Configurable> list = new ArrayList<Configurable>();
+ add(list, configurables);
+ return list;
+ }
+
+ private void add(List<Configurable> list, Configurable... configurables) {
+ for (Configurable configurable : configurables) {
+ if (accept(configurable)) {
+ list.add(configurable);
+ }
+ if (configurable instanceof Configurable.Composite) {
+ Configurable.Composite composite = (Configurable.Composite)configurable;
+ add(list, composite.getConfigurables());
+ }
+ }
+ }
+
+ public static final class ByID extends ConfigurableVisitor {
+ private final String myID;
+
+ public ByID(@NotNull String id) {
+ myID = id;
+ }
+
+ @Override
+ protected boolean accept(Configurable configurable) {
+ return myID.equals(getID(configurable));
+ }
+
+ public static String getID(Configurable configurable) {
+ return configurable instanceof SearchableConfigurable
+ ? ((SearchableConfigurable)configurable).getId()
+ : configurable.getClass().getName();
+ }
+ }
+
+ public static final class ByName extends ConfigurableVisitor {
+ private final String myName;
+
+ public ByName(@NotNull String name) {
+ myName = name;
+ }
+
+ @Override
+ protected boolean accept(Configurable configurable) {
+ return myName.equals(configurable.getDisplayName());
+ }
+ }
+
+ public static final class ByType extends ConfigurableVisitor {
+ private final Class<? extends Configurable> myType;
+
+ public ByType(@NotNull Class<? extends Configurable> type) {
+ myType = type;
+ }
+
+ @Override
+ protected boolean accept(Configurable configurable) {
+ if (myType.isInstance(configurable)) {
+ return true;
+ }
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return myType.isInstance(wrapper.getConfigurable());
+ }
+ return false;
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
index 3b67a3478368..dd8169e159a7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
@@ -47,6 +47,9 @@ public class ConfigurableWrapper implements SearchableConfigurable {
@Nullable
public static <T extends UnnamedConfigurable> T wrapConfigurable(ConfigurableEP<T> ep) {
+ if (!ep.canCreateConfigurable()) {
+ return null;
+ }
if (ep.displayName != null || ep.key != null || ep.groupId != null) {
T configurable = null;
if (ep.providerClass != null) {
@@ -55,9 +58,9 @@ public class ConfigurableWrapper implements SearchableConfigurable {
return null; // it is allowed to return null from provider
}
}
- return ep.children != null || ep.childrenEPName != null || ep.dynamic
- ? (T)new CompositeWrapper(ep, configurable)
- : (T)new ConfigurableWrapper(ep, configurable);
+ return !ep.dynamic && ep.children == null && ep.childrenEPName == null
+ ? (T)new ConfigurableWrapper(ep, configurable)
+ : (T)new CompositeWrapper(ep, configurable);
}
else {
return ep.createConfigurable();
@@ -157,7 +160,16 @@ public class ConfigurableWrapper implements SearchableConfigurable {
@NotNull
@Override
public String getId() {
- return myEp.id == null ? myEp.instanceClass == null ? myEp.providerClass : myEp.instanceClass : myEp.id;
+ if (myEp.id != null) {
+ return myEp.id;
+ }
+ UnnamedConfigurable configurable = getConfigurable();
+ if (configurable instanceof SearchableConfigurable) {
+ return ((SearchableConfigurable)configurable).getId();
+ }
+ return myEp.instanceClass != null
+ ? myEp.instanceClass
+ : myEp.providerClass;
}
@NotNull
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
deleted file mode 100644
index e3404ec017cd..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options.ex;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurableGroup;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.OptionsBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import javax.swing.JComponent;
-
-public final class MixedConfigurableGroup implements SearchableConfigurable, ConfigurableGroup {
- private final String myGroupId;
- private Configurable[] myConfigurables;
-
- private MixedConfigurableGroup(String groupId, ArrayList<Configurable> configurables) {
- myGroupId = groupId;
- myConfigurables = (configurables != null)
- ? configurables.toArray(new Configurable[configurables.size()])
- : new Configurable[0];
- Arrays.sort(myConfigurables, COMPARATOR);
- }
-
- private MixedConfigurableGroup(String groupId, HashMap<String, ArrayList<Configurable>> configurables) {
- this(groupId, configurables.remove(groupId));
- }
-
- @Override
- public JComponent createComponent() {
- return null;
- }
-
- @Override
- public boolean isModified() {
- return false;
- }
-
- @Override
- public void apply() throws ConfigurationException {
- }
-
- @Override
- public void reset() {
- }
-
- @Override
- public void disposeUIResources() {
- myConfigurables = null;
- }
-
- @Override
- public Runnable enableSearch(String option) {
- return null;
- }
-
- @NotNull
- @Override
- public String getId() {
- return "configurable.group." + myGroupId;
- }
-
- @Override
- public String getHelpTopic() {
- return "configurable.group." + myGroupId + ".help.topic";
- }
-
- @Override
- public String getDisplayName() {
- return OptionsBundle.message("configurable.group." + myGroupId + ".settings.display.name");
- }
-
- @Override
- public String getShortName() {
- return getDisplayName();
- }
-
- @Override
- public Configurable[] getConfigurables() {
- return myConfigurables;
- }
-
- public static ConfigurableGroup[] getGroups(Configurable... configurables) {
- HashMap<String, ArrayList<Configurable>> map = new HashMap<String, ArrayList<Configurable>>();
- for (Configurable configurable : configurables) {
- String groupId = null;
- if (configurable instanceof ConfigurableWrapper) {
- groupId = ((ConfigurableWrapper)configurable).getExtensionPoint().groupId;
- }
- ArrayList<Configurable> list = map.get(groupId);
- if (list == null) {
- map.put(groupId, list = new ArrayList<Configurable>());
- }
- list.add(configurable);
- }
- ArrayList<Configurable> buildList = map.get("build");
- if (buildList != null) {
- NodeConfigurable buildTools = new NodeConfigurable("build.tools", 1000);
- buildTools.add(find("MavenSettings", buildList.iterator()));
- buildTools.add(find("reference.settingsdialog.project.gradle", buildList.iterator()));
- buildTools.add(find("reference.settingsdialog.project.gant", buildList.iterator()));
- if (buildTools.getConfigurables() != null) {
- buildList.add(0, buildTools);
- }
- }
- ArrayList<ConfigurableGroup> groups = new ArrayList<ConfigurableGroup>(map.size());
- groups.add(new MixedConfigurableGroup("appearance", map));
- groups.add(new MixedConfigurableGroup("editor", map));
- groups.add(new MixedConfigurableGroup("project", map));
- groups.add(new MixedConfigurableGroup("build", map));
- groups.add(new MixedConfigurableGroup("language", map));
- groups.add(new MixedConfigurableGroup("tools", map));
- ConfigurableGroup other = new MixedConfigurableGroup(null, map);
- for(Entry<String, ArrayList<Configurable>>entry: map.entrySet()){
- groups.add(new MixedConfigurableGroup(entry.getKey(), entry.getValue()));
- }
- groups.add(other);
- return groups.toArray(new ConfigurableGroup[groups.size()]);
- }
-
- private static Configurable find(String id, Iterator<Configurable> iterator) {
- while (iterator.hasNext()) {
- Configurable configurable = iterator.next();
- if (configurable instanceof SearchableConfigurable) {
- SearchableConfigurable sc = (SearchableConfigurable)configurable;
- if (id.equals(sc.getId())) {
- iterator.remove();
- return configurable;
- }
- }
- }
- return null;
- }
-
- public static int getGroupWeight(Configurable configurable) {
- if (configurable instanceof NodeConfigurable) {
- return ((NodeConfigurable)configurable).getGroupWeight();
- }
- if (configurable instanceof ConfigurableWrapper) {
- return ((ConfigurableWrapper)configurable).getExtensionPoint().groupWeight;
- }
- return 0;
- }
-
- private static final Comparator<Configurable> COMPARATOR = new Comparator<Configurable>() {
- @Override
- public int compare(Configurable configurable1, Configurable configurable2) {
- if (configurable1 == null || configurable2 == null) {
- return configurable2 != null ? -1 : configurable1 != null ? 1 : 0;
- }
- int weight1 = getGroupWeight(configurable1);
- int weight2 = getGroupWeight(configurable2);
- return weight1 > weight2 ? -1 : weight1 < weight2 ? 1 : StringUtil.naturalCompare(configurable1.getDisplayName(),
- configurable2.getDisplayName());
- }
- };
-}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
deleted file mode 100644
index 609943d02943..000000000000
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.options.ex;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.OptionsBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-
-public final class NodeConfigurable extends SearchableConfigurable.Parent.Abstract {
- private final ArrayList<Configurable> myConfigurables = new ArrayList<Configurable>();
- private final String myId;
- private final int myWeight;
-
- public NodeConfigurable(@NotNull String id, int weight) {
- myId = id;
- myWeight = weight;
- }
-
- public int getGroupWeight() {
- return myWeight;
- }
-
- public void add(Configurable configurable) {
- if (configurable != null) {
- super.disposeUIResources();
- myConfigurables.add(configurable);
- }
- }
-
- @Override
- public void disposeUIResources() {
- super.disposeUIResources();
- myConfigurables.clear();
- }
-
- @NotNull
- @Override
- public String getId() {
- return "node.configurable." + myId;
- }
-
- @Nullable
- @Override
- public String getHelpTopic() {
- return "node.configurable." + myId + ".help.topic";
- }
-
- @Nls
- @Override
- public String getDisplayName() {
- return OptionsBundle.message("node.configurable." + myId + ".display.name");
- }
-
- @Override
- protected Configurable[] buildConfigurables() {
- int size = myConfigurables.size();
- return size == 0 ? null : myConfigurables.toArray(new Configurable[size]);
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/SortedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/SortedConfigurableGroup.java
new file mode 100644
index 000000000000..3d87b7679359
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/SortedConfigurableGroup.java
@@ -0,0 +1,195 @@
+/*
+ * 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.ex;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurableGroup;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author Sergey.Malenkov
+ */
+public final class SortedConfigurableGroup
+ extends SearchableConfigurable.Parent.Abstract
+ implements SearchableConfigurable, ConfigurableGroup, Configurable.NoScroll {
+
+ public static ConfigurableGroup getGroup(Configurable... configurables) {
+ SortedConfigurableGroup root = new SortedConfigurableGroup("root");
+ HashMap<String, SortedConfigurableGroup> map = new HashMap<String, SortedConfigurableGroup>();
+ map.put("root", root);
+ for (Configurable configurable : configurables) {
+ int weight = 0;
+ String groupId = null;
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ weight = wrapper.getExtensionPoint().groupWeight;
+ groupId = wrapper.getExtensionPoint().groupId;
+ }
+ SortedConfigurableGroup composite = map.get(groupId);
+ if (composite == null) {
+ composite = new SortedConfigurableGroup(groupId);
+ map.put(groupId, composite);
+ }
+ composite.add(weight, configurable);
+ }
+ // process supported groups
+ root.add(60, map.remove("appearance"));
+ root.add(50, map.remove("editor"));
+ root.add(40, map.remove("project"));
+ SortedConfigurableGroup build = map.remove("build");
+ if (build == null) {
+ build = map.remove("build.tools");
+ }
+ else {
+ build.add(1000, map.remove("build.tools"));
+ }
+ root.add(30, build);
+ root.add(20, map.remove("language"));
+ root.add(10, map.remove("tools"));
+ root.add(-10, map.remove(null));
+ // process unsupported groups
+ if (1 < map.size()) {
+ for (SortedConfigurableGroup group : map.values()) {
+ if (root != group) {
+ group.myDisplayName = "Category: " + group.myGroupId;
+ root.add(0, group);
+ }
+ }
+ }
+ return root;
+ }
+
+ private final ArrayList<WeightConfigurable> myList = new ArrayList<WeightConfigurable>();
+ private final String myGroupId;
+ private String myDisplayName;
+
+ private SortedConfigurableGroup(String groupId) {
+ myGroupId = groupId;
+ }
+
+ public SortedConfigurableGroup(Configurable... configurables) {
+ myGroupId = "root";
+ // create groups from configurations
+ HashMap<String, SortedConfigurableGroup> map = new HashMap<String, SortedConfigurableGroup>();
+ map.put(myGroupId, this);
+ for (Configurable configurable : configurables) {
+ int weight = 0;
+ String groupId = null;
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ weight = wrapper.getExtensionPoint().groupWeight;
+ groupId = wrapper.getExtensionPoint().groupId;
+ }
+ SortedConfigurableGroup composite = map.get(groupId);
+ if (composite == null) {
+ composite = new SortedConfigurableGroup(groupId);
+ map.put(groupId, composite);
+ }
+ composite.add(weight, configurable);
+ }
+ // process supported groups
+ add(60, map.remove("appearance"));
+ add(50, map.remove("editor"));
+ add(40, map.remove("project"));
+ SortedConfigurableGroup build = map.remove("build");
+ if (build == null) {
+ build = map.remove("build.tools");
+ }
+ else {
+ build.add(1000, map.remove("build.tools"));
+ }
+ add(30, build);
+ add(20, map.remove("language"));
+ add(10, map.remove("tools"));
+ add(-10, map.remove(null));
+ // process unsupported groups
+ if (1 < map.size()) {
+ for (SortedConfigurableGroup group : map.values()) {
+ if (this != group) {
+ group.myDisplayName = "Category: " + group.myGroupId;
+ add(0, group);
+ }
+ }
+ }
+ }
+
+ private void add(int weight, Configurable configurable) {
+ if (configurable != null) {
+ myList.add(new WeightConfigurable(configurable, weight));
+ }
+ }
+
+ @Override
+ protected Configurable[] buildConfigurables() {
+ Collections.sort(myList);
+ int length = myList.size();
+ Configurable[] result = new Configurable[length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = myList.get(i).myConfigurable;
+ }
+ myList.clear();
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return "configurable.group." + myGroupId;
+ }
+
+ @Nullable
+ @Override
+ public String getHelpTopic() {
+ return "configurable.group." + myGroupId + ".help.topic";
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return myDisplayName != null ? myDisplayName : OptionsBundle.message("configurable.group." + myGroupId + ".settings.display.name");
+ }
+
+ @Override
+ public String getShortName() {
+ return getDisplayName();
+ }
+
+ private static final class WeightConfigurable implements Comparable<WeightConfigurable> {
+ private final Configurable myConfigurable;
+ private final int myWeight;
+
+ private WeightConfigurable(@NotNull Configurable configurable, int weight) {
+ myConfigurable = configurable;
+ myWeight = weight;
+ }
+
+ @Override
+ public int compareTo(@NotNull WeightConfigurable pair) {
+ return myWeight > pair.myWeight ? -1 :
+ myWeight < pair.myWeight ? 1 :
+ StringUtil.naturalCompare(myConfigurable.getDisplayName(), pair.myConfigurable.getDisplayName());
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
index c38bf6ff2033..a995ea372d99 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/IdeSettingsDialog.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.options.newEditor;
import com.intellij.CommonBundle;
-import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationManager;
@@ -25,6 +24,7 @@ import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ex.ConfigurableVisitor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.ActionCallback;
@@ -45,7 +45,6 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
/**
@@ -114,7 +113,7 @@ public class IdeSettingsDialog extends DialogWrapper implements DataProvider {
@Nullable
private static Configurable getPreselectedByDisplayName(final ConfigurableGroup[] groups, final String preselectedConfigurableDisplayName,
final Project project) {
- Configurable result = findPreselectedByDisplayName(preselectedConfigurableDisplayName, groups);
+ Configurable result = new ConfigurableVisitor.ByName(preselectedConfigurableDisplayName).find(groups);
return result == null ? findLastSavedConfigurable(groups, project) : result;
}
@@ -230,44 +229,7 @@ public class IdeSettingsDialog extends DialogWrapper implements DataProvider {
final String id = PropertiesComponent.getInstance(project).getValue(LAST_SELECTED_CONFIGURABLE);
if (id == null) return null;
- return findConfigurableInGroups(id, groups);
- }
-
- @Nullable
- private static Configurable findConfigurableInGroups(String id, Configurable.Composite... groups) {
- // avoid unnecessary group expand: check top-level configurables in all groups before looking at children
- for (Configurable.Composite group : groups) {
- final Configurable[] configurables = group.getConfigurables();
- for (Configurable c : configurables) {
- if (c instanceof SearchableConfigurable && id.equals(((SearchableConfigurable)c).getId())) {
- return c;
- }
- else if (id.equals(c.getClass().getName())) {
- return c;
- }
- }
- }
- for (Configurable.Composite group : groups) {
- final Configurable[] configurables = group.getConfigurables();
- for (Configurable c : configurables) {
- if (c instanceof Configurable.Composite) {
- Configurable result = findConfigurableInGroups(id, (Configurable.Composite)c);
- if (result != null) {
- return result;
- }
- }
- }
- }
- return null;
- }
-
- @Nullable
- private static Configurable findPreselectedByDisplayName(final String preselectedConfigurableDisplayName, ConfigurableGroup[] groups) {
- final List<Configurable> all = SearchUtil.expand(groups);
- for (Configurable each : all) {
- if (preselectedConfigurableDisplayName.equals(each.getDisplayName())) return each;
- }
- return null;
+ return new ConfigurableVisitor.ByID(id).find(groups);
}
@Override
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 c2119596a06e..c1e55a1419a2 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
@@ -17,7 +17,6 @@ package com.intellij.openapi.options.newEditor;
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
-import com.intellij.icons.AllIcons;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.ide.ui.search.SearchUtil;
@@ -1219,27 +1218,31 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
* @return default view for the specified configurable
*/
private JComponent createDefaultComponent(SearchableConfigurable searchable) {
- JPanel box = new JPanel();
- box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
+ JPanel panel = new JPanel(new BorderLayout(0, 9));
try {
- box.add(new JLabel(getDefaultDescription(searchable)));
+ panel.add(BorderLayout.NORTH, new JLabel(getDefaultDescription(searchable)));
}
catch (AssertionError error) {
return null; // description is not set
}
if (searchable instanceof Configurable.Composite) {
- box.add(Box.createVerticalStrut(10));
+ JPanel box = new JPanel();
+ box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
+ panel.add(BorderLayout.CENTER, box);
+
Configurable.Composite composite = (Configurable.Composite)searchable;
for (final Configurable configurable : composite.getConfigurables()) {
- box.add(new LinkLabel(configurable.getDisplayName(), AllIcons.Ide.Link) {
+ LinkLabel label = new LinkLabel(configurable.getDisplayName(), null) {
@Override
public void doClick() {
select(configurable, null);
}
- });
+ };
+ label.setBorder(BorderFactory.createEmptyBorder(1, 17, 1, 1));
+ box.add(label);
}
}
- return box;
+ return panel;
}
@NotNull
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 aee9e889fdf1..ed52a7f50bf6 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
@@ -23,7 +23,6 @@ import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ex.ConfigurableWrapper;
-import com.intellij.openapi.options.ex.NodeConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
@@ -383,17 +382,6 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
SimpleNode parent = base.getParent();
if (parent == myRoot) {
project = getConfigurableProject(base); // show icon for top-level nodes
- if (base.getConfigurable() instanceof NodeConfigurable) { // special case for custom subgroups (build.tools)
- Configurable[] configurables = ((NodeConfigurable)base.getConfigurable()).getConfigurables();
- if (configurables != null) { // assume that all configurables have the same project
- project = getConfigurableProject(configurables[0]);
- }
- }
- }
- else if (parent instanceof Base && ((Base)parent).getConfigurable() instanceof NodeConfigurable) {
- if (((Base)base.getParent()).getConfigurable() instanceof NodeConfigurable) {
- project = getConfigurableProject(base); // special case for custom subgroups
- }
}
}
if (project != null) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
index e10367d583bf..817a042c9bc9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
@@ -20,7 +20,7 @@ import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.*;
import com.intellij.openapi.options.ex.ConfigurableWrapper;
-import com.intellij.openapi.options.ex.NodeConfigurable;
+import com.intellij.openapi.options.ex.SortedConfigurableGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
@@ -49,6 +49,7 @@ import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.TreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
@@ -63,6 +64,7 @@ import java.util.List;
* @author Sergey.Malenkov
*/
final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague {
+ private static final String NODE_ICON = "settings.tree.view.icon";
private static final Color NORMAL_NODE = new JBColor(Gray._60, Gray._140);
private static final Color WRONG_CONTENT = JBColor.RED;
private static final Color MODIFIED_CONTENT = JBColor.BLUE;
@@ -74,8 +76,9 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private final MyRoot myRoot;
private final JScrollPane myScroller;
private JLabel mySeparator;
- private final MyRenderer myRenderer = new MyRenderer();
private final IdentityHashMap<Configurable, MyNode> myConfigurableToNodeMap = new IdentityHashMap<Configurable, MyNode>();
+ private final IdentityHashMap<UnnamedConfigurable, ConfigurableWrapper> myConfigurableToWrapperMap
+ = new IdentityHashMap<UnnamedConfigurable, ConfigurableWrapper>();
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("SettingsTreeView", 150, false, this, this, this)
.setRestartTimerOnAdd(true);
@@ -96,9 +99,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myTree.setRowHeight(-1);
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
- myTree.setCellRenderer(myRenderer);
+ myTree.setCellRenderer(new MyRenderer());
myTree.setRootVisible(false);
myTree.setShowsRootHandles(false);
+ myTree.setExpandableItemsEnabled(false);
myScroller = ScrollPaneFactory.createScrollPane(myTree, true);
myScroller.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
@@ -139,7 +143,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@NotNull
String[] getPathNames(Configurable configurable) {
ArrayDeque<String> path = new ArrayDeque<String>();
- MyNode node = myConfigurableToNodeMap.get(configurable);
+ MyNode node = findNode(configurable);
while (node != null) {
path.push(node.myDisplayName);
SimpleNode parent = node.getParent();
@@ -157,8 +161,9 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Nullable
- SimpleNode findNode(Configurable configurable) {
- return myConfigurableToNodeMap.get(configurable);
+ MyNode findNode(Configurable configurable) {
+ ConfigurableWrapper wrapper = myConfigurableToWrapperMap.get(configurable);
+ return myConfigurableToNodeMap.get(wrapper != null ? wrapper : configurable);
}
@Nullable
@@ -180,6 +185,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (configurable instanceof ConfigurableWrapper) {
ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
configurable = wrapper.getConfigurable();
+ myConfigurableToWrapperMap.put(configurable, wrapper);
}
if (type.isInstance(configurable)) {
return type.cast(configurable);
@@ -194,7 +200,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
return wrapper.getExtensionPoint().getProject();
}
- return findConfigurableProject(myConfigurableToNodeMap.get(configurable));
+ return findConfigurableProject(findNode(configurable));
}
@Nullable
@@ -214,15 +220,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Nullable
- private ConfigurableGroup findConfigurableGroupAt(int x, int y) {
+ private String findGroupNameAt(int x, int y) {
TreePath path = myTree.getClosestPathForLocation(x - myTree.getX(), y - myTree.getY());
while (path != null) {
MyNode node = extractNode(path);
if (node == null) {
return null;
}
- if (node.myComposite instanceof ConfigurableGroup) {
- return (ConfigurableGroup)node.myComposite;
+ if (myRoot == node.getParent()) {
+ return node.myDisplayName;
}
path = path.getParentPath();
}
@@ -267,10 +273,10 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
mySeparator.setFont(getFont().deriveFont(Font.BOLD));
}
int height = mySeparator.getPreferredSize().height;
- ConfigurableGroup group = findConfigurableGroupAt(0, height);
- if (group != null && group == findConfigurableGroupAt(0, -myRenderer.getSeparatorHeight())) {
+ String group = findGroupNameAt(0, height);
+ if (group != null && group.equals(findGroupNameAt(0, 0))) {
mySeparator.setBorder(BorderFactory.createEmptyBorder(0, 18, 0, 0));
- mySeparator.setText(group.getDisplayName());
+ mySeparator.setText(group);
Rectangle bounds = myScroller.getViewport().getBounds();
if (bounds.height > height) {
@@ -319,7 +325,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
public void run() {
if (configurable != myQueuedConfigurable) return;
- MyNode editorNode = myConfigurableToNodeMap.get(configurable);
+ MyNode editorNode = findNode(configurable);
FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode);
if (editorUiNode == null) return;
@@ -353,7 +359,8 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
private void fireSelected(Configurable configurable, ActionCallback callback) {
- myFilter.myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
+ ConfigurableWrapper wrapper = myConfigurableToWrapperMap.get(configurable);
+ myFilter.myContext.fireSelected(wrapper != null ? wrapper : configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
}
@Override
@@ -396,11 +403,13 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (myGroups == null || myGroups.length == 0) {
return NO_CHILDREN;
}
- SimpleNode[] result = new SimpleNode[myGroups.length];
- for (int i = 0; i < myGroups.length; i++) {
- result[i] = new MyNode(this, myGroups[i]);
+ ArrayList<MyNode> list = new ArrayList<MyNode>();
+ for (ConfigurableGroup group : myGroups) {
+ for (Configurable configurable : group.getConfigurables()) {
+ list.add(new MyNode(this, configurable, 0));
+ }
}
- return result;
+ return list.toArray(new SimpleNode[list.size()]);
}
}
@@ -408,21 +417,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
private final Configurable.Composite myComposite;
private final Configurable myConfigurable;
private final String myDisplayName;
+ private final int myLevel;
- private MyNode(CachingSimpleNode parent, Configurable configurable) {
+ private MyNode(CachingSimpleNode parent, Configurable configurable, int level) {
super(parent);
myComposite = configurable instanceof Configurable.Composite ? (Configurable.Composite)configurable : null;
myConfigurable = configurable;
String name = configurable.getDisplayName();
myDisplayName = name != null ? name.replace("\n", " ") : "{ " + configurable.getClass().getSimpleName() + " }";
- }
-
- private MyNode(CachingSimpleNode parent, ConfigurableGroup group) {
- super(parent);
- myComposite = group;
- myConfigurable = group instanceof Configurable ? (Configurable)group : null;
- String name = group.getDisplayName();
- myDisplayName = name != null ? name.replace("\n", " ") : "{ " + group.getClass().getSimpleName() + " }";
+ myLevel = level;
}
@Override
@@ -439,7 +442,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
SimpleNode[] result = new SimpleNode[configurables.length];
for (int i = 0; i < configurables.length; i++) {
- result[i] = new MyNode(this, configurables[i]);
+ result[i] = new MyNode(this, configurables[i], myLevel + 1);
if (myConfigurable != null) {
myFilter.myContext.registerKid(myConfigurable, configurables[i]);
}
@@ -453,25 +456,17 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
}
- private final class MyRenderer extends GroupedElementsRenderer.Tree {
- private JLabel myNodeIcon;
- private JLabel myProjectIcon;
-
- protected JComponent createItemComponent() {
- myTextLabel = new ErrorLabel();
- return myTextLabel;
- }
+ private final class MyRenderer extends JPanel implements TreeCellRenderer {
+ private final JLabel myTextLabel = new ErrorLabel();
+ private final JLabel myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
+ private final JLabel myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
- @Override
- protected void layout() {
- myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
- myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
- myNodeIcon.setOpaque(false);
- myTextLabel.setOpaque(false);
- myProjectIcon.setOpaque(false);
- myRendererComponent.add(BorderLayout.CENTER, myComponent);
- myRendererComponent.add(BorderLayout.WEST, myNodeIcon);
- myRendererComponent.add(BorderLayout.EAST, myProjectIcon);
+ public MyRenderer() {
+ super(new BorderLayout());
+ myNodeIcon.setName(NODE_ICON);
+ add(BorderLayout.CENTER, myTextLabel);
+ add(BorderLayout.WEST, myNodeIcon);
+ add(BorderLayout.EAST, myProjectIcon);
}
public Component getTreeCellRendererComponent(JTree tree,
@@ -482,7 +477,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
int row,
boolean focused) {
myTextLabel.setFont(UIUtil.getLabelFont());
- myRendererComponent.setBackground(selected ? UIUtil.getTreeSelectionBackground() : myTree.getBackground());
+ setPreferredSize(null);
MyNode node = extractNode(value);
if (node == null) {
@@ -494,28 +489,19 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (myRoot == node.getParent()) {
myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
}
- TreePath path = tree.getPathForRow(row);
- if (path == null) {
- if (value instanceof DefaultMutableTreeNode) {
- path = new TreePath(((DefaultMutableTreeNode)value).getPath());
- }
- }
- int forcedWidth = 2000;
- if (path != null && tree.isVisible()) {
- Rectangle visibleRect = tree.getVisibleRect();
-
- int nestingLevel = tree.isRootVisible() ? path.getPathCount() - 1 : path.getPathCount() - 2;
-
- int left = UIUtil.getTreeLeftChildIndent();
- int right = UIUtil.getTreeRightChildIndent();
-
+ if (tree.isVisible()) {
+ int indent = node.myLevel * (UIUtil.getTreeLeftChildIndent() + UIUtil.getTreeRightChildIndent());
Insets treeInsets = tree.getInsets();
-
- int indent = (left + right) * nestingLevel + (treeInsets != null ? treeInsets.left + treeInsets.right : 0);
-
- forcedWidth = visibleRect.width > 0 ? visibleRect.width - indent : forcedWidth;
+ if (treeInsets != null) {
+ indent += treeInsets.left + treeInsets.right;
+ }
+ int visibleWidth = tree.getVisibleRect().width;
+ if (visibleWidth > indent) {
+ Dimension size = getPreferredSize();
+ size.width = visibleWidth - indent;
+ //setPreferredSize(size);
+ }
}
- myRendererComponent.setPrefereedWidth(forcedWidth - 4);
}
// update font color for modified configurables
myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground() : NORMAL_NODE);
@@ -537,15 +523,15 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
if (parent instanceof MyNode) {
if (myRoot == parent.getParent()) {
project = findConfigurableProject(node); // show icon for top-level nodes
- if (node.myConfigurable instanceof NodeConfigurable) { // special case for custom subgroups (build.tools)
- Configurable[] configurables = ((NodeConfigurable)node.myConfigurable).getConfigurables();
+ if (node.myConfigurable instanceof SortedConfigurableGroup) { // special case for custom subgroups (build.tools)
+ Configurable[] configurables = ((SortedConfigurableGroup)node.myConfigurable).getConfigurables();
if (configurables != null) { // assume that all configurables have the same project
project = findConfigurableProject(configurables[0]);
}
}
}
- else if (((MyNode)parent).myConfigurable instanceof NodeConfigurable) {
- if (((MyNode)node.getParent()).myConfigurable instanceof NodeConfigurable) {
+ else if (((MyNode)parent).myConfigurable instanceof SortedConfigurableGroup) {
+ if (((MyNode)node.getParent()).myConfigurable instanceof SortedConfigurableGroup) {
project = findConfigurableProject(node); // special case for custom subgroups
}
}
@@ -564,25 +550,20 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
myProjectIcon.setVisible(false);
}
// configure node icon
- if (value instanceof DefaultMutableTreeNode) {
- DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
- TreePath treePath = new TreePath(treeNode.getPath());
- myNodeIcon.setIcon(myTree.getHandleIcon(treeNode, treePath));
- }
- else {
- myNodeIcon.setIcon(null);
+ Icon nodeIcon = null;
+ if (node != null) {
+ if (0 == node.getChildCount()) {
+ nodeIcon = myTree.getEmptyHandle();
+ }
+ else if (value instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
+ nodeIcon = myTree.isExpanded(new TreePath(treeNode.getPath()))
+ ? myTree.getExpandedHandle()
+ : myTree.getCollapsedHandle();
+ }
}
- return myRendererComponent;
- }
-
- int getSeparatorHeight() {
- return mySeparatorComponent.getParent() == null ? 0 : mySeparatorComponent.getPreferredSize().height;
- }
-
- public boolean isUnderHandle(Point point) {
- Point handlePoint = SwingUtilities.convertPoint(myRendererComponent, point, myNodeIcon);
- Rectangle bounds = myNodeIcon.getBounds();
- return bounds.x < handlePoint.x && bounds.getMaxX() >= handlePoint.x;
+ myNodeIcon.setIcon(nodeIcon);
+ return this;
}
}
@@ -616,11 +597,7 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
@Override
public void setUI(TreeUI ui) {
- TreeUI actualUI = ui;
- if (!(ui instanceof MyTreeUi)) {
- actualUI = new MyTreeUi();
- }
- super.setUI(actualUI);
+ super.setUI(ui instanceof MyTreeUi ? ui : new MyTreeUi());
}
@Override
@@ -659,84 +636,92 @@ final class SettingsTreeView extends JComponent implements Disposable, OptionsEd
}
@Override
- protected void processMouseEvent(MouseEvent e) {
+ protected void processMouseEvent(MouseEvent event) {
MyTreeUi ui = (MyTreeUi)myTree.getUI();
- boolean toggleNow = MouseEvent.MOUSE_RELEASED == e.getID()
- && UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED)
- && !ui.isToggleEvent(e);
-
- if (toggleNow || MouseEvent.MOUSE_PRESSED == e.getID()) {
- TreePath path = getPathForLocation(e.getX(), e.getY());
- if (path != null) {
- Rectangle bounds = getPathBounds(path);
- if (bounds != null && path.getLastPathComponent() instanceof DefaultMutableTreeNode) {
- DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
- boolean selected = isPathSelected(path);
- boolean expanded = isExpanded(path);
- Component comp =
- myRenderer.getTreeCellRendererComponent(this, node, selected, expanded, node.isLeaf(), getRowForPath(path), isFocusOwner());
-
- comp.setBounds(bounds);
- comp.validate();
-
- Point point = new Point(e.getX() - bounds.x, e.getY() - bounds.y);
- if (myRenderer.isUnderHandle(point)) {
- if (toggleNow) {
- ui.toggleExpandState(path);
- }
- e.consume();
- return;
- }
- }
- }
+ if (!ui.processMouseEvent(event)) {
+ super.processMouseEvent(event);
}
-
- super.processMouseEvent(e);
}
+ }
- private final class MyTreeUi extends WideSelectionTreeUI {
+ private static final class MyTreeUi extends WideSelectionTreeUI {
+ boolean processMouseEvent(MouseEvent event) {
+ if (super.tree instanceof SimpleTree) {
+ SimpleTree tree = (SimpleTree)super.tree;
- @Override
- public void toggleExpandState(TreePath path) {
- super.toggleExpandState(path);
- }
+ boolean toggleNow = MouseEvent.MOUSE_RELEASED == event.getID()
+ && UIUtil.isActionClick(event, MouseEvent.MOUSE_RELEASED)
+ && !isToggleEvent(event);
- @Override
- public boolean isToggleEvent(MouseEvent event) {
- return super.isToggleEvent(event);
+ if (toggleNow || MouseEvent.MOUSE_PRESSED == event.getID()) {
+ Component component = tree.getDeepestRendererComponentAt(event.getX(), event.getY());
+ if (component != null && NODE_ICON.equals(component.getName())) {
+ if (toggleNow) {
+ toggleExpandState(tree.getPathForLocation(event.getX(), event.getY()));
+ }
+ event.consume();
+ return true;
+ }
+ }
}
+ return false;
+ }
- @Override
- protected boolean shouldPaintExpandControl(TreePath path,
- int row,
- boolean isExpanded,
- boolean hasBeenExpanded,
- boolean isLeaf) {
- return false;
- }
+ @Override
+ protected boolean shouldPaintExpandControl(TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+ return false;
+ }
- @Override
- protected void paintHorizontalPartOfLeg(Graphics g,
- Rectangle clipBounds,
- Insets insets,
- Rectangle bounds,
- TreePath path,
- int row,
- boolean isExpanded,
- boolean hasBeenExpanded,
- boolean isLeaf) {
+ @Override
+ protected void paintHorizontalPartOfLeg(Graphics g,
+ Rectangle clipBounds,
+ Insets insets,
+ Rectangle bounds,
+ TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
- }
+ }
- @Override
- protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) {
- }
+ @Override
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) {
+ }
- @Override
- public void paint(Graphics g, JComponent c) {
- GraphicsUtil.setupAntialiasing(g);
- super.paint(g, c);
+ @Override
+ public void paint(Graphics g, JComponent c) {
+ GraphicsUtil.setupAntialiasing(g);
+ super.paint(g, c);
+ }
+
+ @Override
+ protected void paintRow(Graphics g,
+ Rectangle clipBounds,
+ Insets insets,
+ Rectangle bounds,
+ TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+ if (tree != null) {
+ int width = tree.getWidth();
+ Container parent = tree.getParent();
+ if (parent instanceof JViewport) {
+ JViewport viewport = (JViewport)parent;
+ width = viewport.getWidth() - viewport.getViewPosition().x;
+ }
+ width -= bounds.x;
+ if (bounds.width < width) {
+ bounds.width = width;
+ }
}
+ super.paintRow(g, clipBounds, insets, bounds, path, row, isExpanded, hasBeenExpanded, isLeaf);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
index 308edb2d81a6..c66eb5eb1a27 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
@@ -34,7 +34,6 @@ import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
import com.intellij.openapi.wm.ex.StatusBarEx;
-import com.intellij.psi.impl.DebugUtil;
import com.intellij.ui.AppIcon;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
@@ -81,7 +80,7 @@ public class DumbServiceImpl extends DumbService implements Disposable {
@Override
public void cancelTask(@NotNull DumbModeTask task) {
- if (ApplicationManager.getApplication().isInternal()) LOG.info("cancel " + task + "\n" + DebugUtil.currentStackTrace());
+ if (ApplicationManager.getApplication().isInternal()) LOG.info("cancel " + task);
ProgressIndicatorEx indicator = myProgresses.get(task);
if (indicator != null) {
indicator.cancel();
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
index 978e20f6b532..8725dc003da5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
@@ -38,7 +38,6 @@ import com.intellij.openapi.components.impl.stores.IProjectStore;
import com.intellij.openapi.components.impl.stores.StoreUtil;
import com.intellij.openapi.components.impl.stores.UnknownMacroNotification;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.util.pico.ConstructorInjectionComponentAdapter;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -58,6 +57,8 @@ import com.intellij.openapi.wm.impl.FrameTitleBuilder;
import com.intellij.util.Function;
import com.intellij.util.TimedReference;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.pico.ConstructorInjectionComponentAdapter;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -488,7 +489,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
}
if (!macros2invalidate.isEmpty()) {
- final Set<String> components = new HashSet<String>();
+ final Set<String> components = new THashSet<String>();
for (TrackingPathMacroSubstitutor substitutor : substitutors) {
components.addAll(substitutor.getComponents(macros2invalidate));
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
index e7b20959369e..b5243e7c7ec9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
@@ -57,7 +57,6 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
-import com.intellij.util.io.fs.IFile;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
@@ -922,9 +921,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
IProjectStore projectStore = projectImpl.getStateStore();
final String location = projectImpl.getPresentableUrl();
- final List<IFile> original;
+ final List<File> original;
try {
- final IComponentStore.SaveSession saveSession = projectStore.startSave();
+ IComponentStore.SaveSession saveSession = projectStore.startSave();
original = saveSession.getAllStorageFiles(true);
saveSession.finishSave();
}
@@ -937,7 +936,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
application.runWriteAction(new Runnable() {
@Override
public void run() {
- for (final IFile originalFile : original) {
+ for (File originalFile : original) {
restoreCopy(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(originalFile));
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/popup/MultiSelectionListPopupStep.java b/platform/platform-impl/src/com/intellij/openapi/ui/popup/MultiSelectionListPopupStep.java
index 815eafd56ab4..96fbccc87054 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/popup/MultiSelectionListPopupStep.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/popup/MultiSelectionListPopupStep.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.
@@ -28,8 +28,8 @@ import java.util.List;
public abstract class MultiSelectionListPopupStep<T> extends BaseListPopupStep<T> {
private int[] myDefaultOptionIndices = ArrayUtil.EMPTY_INT_ARRAY;
- protected MultiSelectionListPopupStep(@Nullable String aTitle, List<? extends T> aValues) {
- super(aTitle, aValues);
+ protected MultiSelectionListPopupStep(@Nullable String title, List<? extends T> values) {
+ super(title, values);
}
public abstract PopupStep<?> onChosen(List<T> selectedValues, boolean finalChoice);
@@ -54,8 +54,8 @@ public abstract class MultiSelectionListPopupStep<T> extends BaseListPopupStep<T
}
@Override
- public final void setDefaultOptionIndex(int aDefaultOptionIndex) {
- myDefaultOptionIndices = new int[]{aDefaultOptionIndex};
+ public final void setDefaultOptionIndex(int defaultOptionIndex) {
+ myDefaultOptionIndices = new int[]{defaultOptionIndex};
}
public int[] getDefaultOptionIndices() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
index 1f331d7f9232..81b51cab9cb2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.updateSettings.impl;
+import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -24,7 +25,7 @@ import com.intellij.openapi.util.SystemInfo;
public class CheckForUpdateAction extends AnAction implements DumbAware {
@Override
public void update(AnActionEvent e) {
- e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu);
+ e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu || !ActionPlaces.MAIN_MENU.equals(e.getPlace()));
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
index 2cee5d3e03f9..be22623c2142 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
@@ -25,7 +25,6 @@
</constraints>
<properties>
<contentType value="text/html"/>
- <text value="&lt;html&gt;&#10; &lt;head&gt;&#10;&#10; &lt;/head&gt;&#10; &lt;body&gt;&#10; &lt;p style=&quot;margin-top: 0&quot;&gt;&#10; &#10; &lt;/p&gt;&#10; &lt;/body&gt;&#10;&lt;/html&gt;&#10;"/>
</properties>
</component>
<vspacer id="bf1d9">
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
index 071a260fe68c..a95597514bb1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
@@ -15,12 +15,14 @@
*/
package com.intellij.openapi.vfs.ex.dummy;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerAdapter;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.BidirectionalMap;
@@ -32,7 +34,6 @@ import org.jetbrains.annotations.TestOnly;
import java.io.IOException;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
/**
@@ -76,11 +77,6 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm
public void projectOpened(final Project project) {
onProjectOpened(project);
}
-
- @Override
- public void projectClosed(final Project project) {
- onProjectClosed(project);
- }
});
initProjectMap();
}
@@ -135,7 +131,16 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm
clearCache();
}
- public void onProjectOpened(Project project) {
+ public void onProjectOpened(final Project project) {
+ // use Disposer instead of ProjectManagerListener#projectClosed() because Disposer.dispose(project)
+ // is called later and some cached files should stay valid till the last moment
+ Disposer.register(project, new Disposable() {
+ @Override
+ public void dispose() {
+ onProjectClosed(project);
+ }
+ });
+
clearCache();
String projectId = project.getLocationHash();
myProject2Id.put(project, projectId);
@@ -157,13 +162,11 @@ public abstract class DummyCachingFileSystem<T extends VirtualFile> extends Dumm
}
protected void clearInvalidFiles() {
- for (Iterator<String> it = myCachedFiles.keySet().iterator(); it.hasNext(); ) {
- String path = it.next();
- T t = myCachedFiles.get(path);
- if (t == null || !t.isValid()) {
- it.remove();
- }
+ for (T t : myCachedFiles.notNullValues()) {
+ if (!t.isValid()) myCachedFiles.removeValue(t);
}
+ //noinspection StatementWithEmptyBody
+ while (myCachedFiles.removeValue(null)) ;
}
@TestOnly
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java
index b6fa97092059..5a0f433c7828 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java
@@ -49,7 +49,7 @@ import java.util.Set;
public class VfsRootAccess {
private static final boolean SHOULD_PERFORM_ACCESS_CHECK = System.getenv("NO_FS_ROOTS_ACCESS_CHECK") == null;
// we don't want test subclasses to accidentally remove allowed files, added by base classes
- private static final Set<String> ourAdditionalRoots = new THashSet<String>();
+ private static final Set<String> ourAdditionalRoots = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
private static boolean insideGettingRoots;
@TestOnly
@@ -109,7 +109,7 @@ public class VfsRootAccess {
Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
if (openProjects.length == 0) return null;
- final Set<String> allowed = new THashSet<String>();
+ final Set<String> allowed = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
allowed.add(FileUtil.toSystemIndependentName(PathManager.getHomePath()));
try {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
index b05b7a285e7b..b8a55b333203 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.ByteSequence;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.newvfs.FileAttribute;
import com.intellij.openapi.vfs.newvfs.impl.FileNameCache;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SystemProperties;
@@ -57,6 +58,7 @@ public class FSRecords implements Forceable {
private static final Logger LOG = Logger.getInstance("#com.intellij.vfs.persistent.FSRecords");
public static final boolean weHaveContentHashes = SystemProperties.getBooleanProperty("idea.share.contents", true);
+ public static final boolean lazyVfsDataCleaning = SystemProperties.getBooleanProperty("idea.lazy.vfs.data.cleaning", true);
private static final int VERSION = 20 + (weHaveContentHashes ? 0x10:0) + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0x37:0);
private static final int PARENT_OFFSET = 0;
@@ -558,6 +560,7 @@ public class FSRecords implements Forceable {
return newRecord;
}
else {
+ if (lazyVfsDataCleaning) deleteContentAndAttributes(free);
DbConnection.cleanRecord(free);
return free;
}
@@ -588,7 +591,33 @@ public class FSRecords implements Forceable {
try {
w.lock();
incModCount(id);
- doDeleteRecursively(id);
+ if (lazyVfsDataCleaning) {
+ markAsDeletedRecursively(id);
+ } else {
+ doDeleteRecursively(id);
+ }
+ }
+ catch (Throwable e) {
+ throw DbConnection.handleError(e);
+ }
+ finally {
+ w.unlock();
+ }
+ }
+
+ private static void markAsDeletedRecursively(final int id) {
+ for (int subrecord : list(id)) {
+ markAsDeletedRecursively(subrecord);
+ }
+
+ markAsDeleted(id);
+ }
+
+ private static void markAsDeleted(final int id) {
+ try {
+ w.lock();
+ DbConnection.markDirty();
+ addToFreeRecordsList(id);
}
catch (Throwable e) {
throw DbConnection.handleError(e);
@@ -1206,12 +1235,26 @@ public class FSRecords implements Forceable {
}
@Nullable
- static DataInputStream readAttributeWithLock(int fileId, String attId) {
+ public static DataInputStream readAttributeWithLock(int fileId, FileAttribute att) {
try {
- synchronized (attId) {
+ synchronized (att.getId()) {
try {
r.lock();
- return readAttribute(fileId, attId);
+ DataInputStream stream = readAttribute(fileId, att.getId());
+ if (stream != null) {
+ try {
+ int actualVersion = DataInputOutputUtil.readINT(stream);
+ if (actualVersion != att.getVersion()) {
+ stream.close();
+ return null;
+ }
+ }
+ catch (IOException e) {
+ stream.close();
+ return null;
+ }
+ }
+ return stream;
}
finally {
r.unlock();
@@ -1280,7 +1323,9 @@ public class FSRecords implements Forceable {
private static void checkFileIsValid(int fileId) {
assert fileId > 0 : fileId;
// TODO: This assertion is a bit timey, will remove when bug is caught.
- assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Accessing attribute of a deleted page: " + fileId + ":" + getName(fileId);
+ if (!lazyVfsDataCleaning) {
+ assert (getFlags(fileId) & FREE_RECORD_FLAG) == 0 : "Accessing attribute of a deleted page: " + fileId + ":" + getName(fileId);
+ }
}
public static int acquireFileContent(int fileId) {
@@ -1374,6 +1419,18 @@ public class FSRecords implements Forceable {
return new AttributeOutputStream(fileId, attId, fixedSize);
}
+ @NotNull
+ public static DataOutputStream writeAttribute(final int fileId, @NotNull FileAttribute att) {
+ DataOutputStream stream = writeAttribute(fileId, att.getId(), att.isFixedSize());
+ try {
+ DataInputOutputUtil.writeINT(stream, att.getVersion());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return stream;
+ }
+
private static class ContentOutputStream extends DataOutputStream {
protected final int myFileId;
protected final boolean myFixedSize;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
index db5de4258d41..6e135018d356 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
@@ -223,13 +223,13 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
@Override
@Nullable
public DataInputStream readAttribute(@NotNull final VirtualFile file, @NotNull final FileAttribute att) {
- return FSRecords.readAttributeWithLock(getFileId(file), att.getId());
+ return FSRecords.readAttributeWithLock(getFileId(file), att);
}
@Override
@NotNull
public DataOutputStream writeAttribute(@NotNull final VirtualFile file, @NotNull final FileAttribute att) {
- return FSRecords.writeAttribute(getFileId(file), att.getId(), att.isFixedSize());
+ return FSRecords.writeAttribute(getFileId(file), att);
}
@Nullable
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/CommandProcessor.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/CommandProcessor.java
index 30777377bc49..746030e68abd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/CommandProcessor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/CommandProcessor.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,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.impl.commands.FinalizableCommand;
import org.jetbrains.annotations.NotNull;
@@ -124,7 +125,7 @@ public final class CommandProcessor implements Runnable {
FinalizableCommand command = myList.remove(0);
if (isEmpty()) {
// memory leak otherwise
- myExpireCondition = Condition.TRUE;
+ myExpireCondition = Conditions.alwaysTrue();
}
return command;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java
index e6c84f5e7768..ba5c59a9ac25 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java
@@ -17,6 +17,7 @@ package com.intellij.openapi.wm.impl;
import com.intellij.ide.actions.ResizeToolWindowAction;
import com.intellij.idea.ActionsBundle;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManagerListener;
@@ -28,6 +29,7 @@ import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.*;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
@@ -54,8 +56,6 @@ import java.util.Map;
*/
public final class InternalDecorator extends JPanel implements Queryable, TypeSafeDataProvider {
- private static final int DIVIDER_WIDTH = UIUtil.isUnderDarcula() ? 2 : 5;
-
private Project myProject;
private WindowInfoImpl myInfo;
private final ToolWindowImpl myToolWindow;
@@ -169,7 +169,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
else if (ToolWindowAnchor.RIGHT == anchor) {
add(myDivider, BorderLayout.WEST);
}
- myDivider.setPreferredSize(new Dimension(DIVIDER_WIDTH, DIVIDER_WIDTH));
+ myDivider.setPreferredSize(new Dimension(0, 0));
}
else { // docked and floating windows don't have divider
remove(myDivider);
@@ -303,10 +303,16 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
@Override
public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) {
- g.setColor(UIUtil.getPanelBackground());
- doPaintBorder(c, g, x, y, width, height);
- g.setColor(new Color(0, 0, 0, 90));
- doPaintBorder(c, g, x, y, width, height);
+ if (UIUtil.isUnderDarcula()) {
+ g.setColor(Gray._40);
+ doPaintBorder(c, g, x, y, width, height);
+ }
+ else {
+ g.setColor(UIUtil.getPanelBackground());
+ doPaintBorder(c, g, x, y, width, height);
+ g.setColor(Gray._155);
+ doPaintBorder(c, g, x, y, width, height);
+ }
}
private void doPaintBorder(Component c, Graphics g, int x, int y, int width, int height) {
@@ -314,18 +320,22 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
if (insets.top > 0) {
UIUtil.drawLine(g, x, y + insets.top - 1, x + width - 1, y + insets.top - 1);
+ UIUtil.drawLine(g, x, y + insets.top, x + width - 1, y + insets.top);
}
if (insets.left > 0) {
- UIUtil.drawLine(g, x, y + insets.top, x, y + height - 1);
+ UIUtil.drawLine(g, x, y, x, y + height);
+ UIUtil.drawLine(g, x + 1, y, x + 1, y + height);
}
if (insets.right > 0) {
- UIUtil.drawLine(g, x + width - 1, y + insets.top, x + width - 1, y + height - 1);
+ UIUtil.drawLine(g, x + width - 1, y + insets.top, x + width - 1, y + height);
+ UIUtil.drawLine(g, x + width, y + insets.top, x + width, y + height);
}
if (insets.bottom > 0) {
- UIUtil.drawLine(g, x, y + height - 1, x + width - 1, y + height - 1);
+ UIUtil.drawLine(g, x, y + height - 1, x + width, y + height - 1);
+ UIUtil.drawLine(g, x, y + height, x + width, y + height);
}
}
@@ -354,7 +364,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
component = parent;
parent = component.getParent();
}
- return new Insets(0, anchor == ToolWindowAnchor.RIGHT ? 1 : 0, 0, anchor == ToolWindowAnchor.LEFT ? 1 : 0);
+ return new Insets(0, anchor == ToolWindowAnchor.RIGHT ? 1 : 0, anchor == ToolWindowAnchor.TOP ? 1 : 0, anchor == ToolWindowAnchor.LEFT ? 1 : 0);
}
@Override
@@ -447,6 +457,10 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
}
}
}
+ String separatorText = group.getTemplatePresentation().getText();
+ if (children.length > 0 && !StringUtil.isEmpty(separatorText)) {
+ main.addAction(new Separator(separatorText), Constraints.FIRST);
+ }
}
/**
@@ -609,135 +623,98 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa
private final class MyDivider extends JPanel {
private boolean myDragging;
private Point myLastPoint;
+ private Disposable myDisposable;
+ private IdeGlassPane myGlassPane;
+
+ private final MouseAdapter myListener = new MyMouseAdapter();
- private MyDivider() {
- myDragging = false;
- enableEvents(MouseEvent.MOUSE_EVENT_MASK | MouseEvent.MOUSE_MOTION_EVENT_MASK);
- setBorder(new DividerBorder());
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ myGlassPane = IdeGlassPaneUtil.find(this);
+ myDisposable = Disposer.newDisposable();
+ myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable);
+ myGlassPane.addMousePreprocessor(myListener, myDisposable);
}
@Override
- protected final void processMouseMotionEvent(final MouseEvent e) {
- super.processMouseMotionEvent(e);
- if (MouseEvent.MOUSE_DRAGGED == e.getID()) {
- myDragging = true;
- final ToolWindowAnchor anchor = myInfo.getAnchor();
- final boolean isVerticalCursor = myInfo.isDocked() ? anchor.isSplitVertically() : anchor.isHorizontal();
- setCursor(isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
- final Point point = e.getPoint();
+ public void removeNotify() {
+ super.removeNotify();
+ if (myDisposable != null && !Disposer.isDisposed(myDisposable)) {
+ Disposer.dispose(myDisposable);
+ }
+ }
+
+ boolean isInDragZone(MouseEvent e) {
+ final Point p = SwingUtilities.convertMouseEvent(e.getComponent(), e, this).getPoint();
+ return Math.abs(myInfo.getAnchor().isHorizontal() ? p.y : p.x) < 6;
+ }
+
+
+ private class MyMouseAdapter extends MouseAdapter {
+
+ private void updateCursor(MouseEvent e) {
+ if (isInDragZone(e)) {
+ myGlassPane.setCursor(MyDivider.this.getCursor(), MyDivider.this);
+ e.consume();
+ }
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ myDragging = isInDragZone(e);
+ updateCursor(e);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ updateCursor(e);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ updateCursor(e);
+ myDragging = false;
+ }
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ updateCursor(e);
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ if (!myDragging) return;
+ MouseEvent event = SwingUtilities.convertMouseEvent(e.getComponent(), e, MyDivider.this);
+ final ToolWindowAnchor anchor = myInfo.getAnchor();
+ final Point point = event.getPoint();
final Container windowPane = InternalDecorator.this.getParent();
- myLastPoint = SwingUtilities.convertPoint(this, point, windowPane);
+ myLastPoint = SwingUtilities.convertPoint(MyDivider.this, point, windowPane);
myLastPoint.x = Math.min(Math.max(myLastPoint.x, 0), windowPane.getWidth());
myLastPoint.y = Math.min(Math.max(myLastPoint.y, 0), windowPane.getHeight());
final Rectangle bounds = InternalDecorator.this.getBounds();
if (anchor == ToolWindowAnchor.TOP) {
- if (myLastPoint.y < DIVIDER_WIDTH) {
- myLastPoint.y = DIVIDER_WIDTH;
- }
InternalDecorator.this.setBounds(0, 0, bounds.width, myLastPoint.y);
}
else if (anchor == ToolWindowAnchor.LEFT) {
- if (myLastPoint.x < DIVIDER_WIDTH) {
- myLastPoint.x = DIVIDER_WIDTH;
- }
InternalDecorator.this.setBounds(0, 0, myLastPoint.x, bounds.height);
}
else if (anchor == ToolWindowAnchor.BOTTOM) {
- if (myLastPoint.y > windowPane.getHeight() - DIVIDER_WIDTH) {
- myLastPoint.y = windowPane.getHeight() - DIVIDER_WIDTH;
- }
InternalDecorator.this.setBounds(0, myLastPoint.y, bounds.width, windowPane.getHeight() - myLastPoint.y);
}
else if (anchor == ToolWindowAnchor.RIGHT) {
- if (myLastPoint.x > windowPane.getWidth() - DIVIDER_WIDTH) {
- myLastPoint.x = windowPane.getWidth() - DIVIDER_WIDTH;
- }
InternalDecorator.this.setBounds(myLastPoint.x, 0, windowPane.getWidth() - myLastPoint.x, bounds.height);
}
InternalDecorator.this.validate();
+ e.consume();
}
}
@Override
- protected final void processMouseEvent(final MouseEvent e) {
- super.processMouseEvent(e);
+ public Cursor getCursor() {
final boolean isVerticalCursor = myInfo.isDocked() ? myInfo.getAnchor().isSplitVertically() : myInfo.getAnchor().isHorizontal();
- switch (e.getID()) {
- case MouseEvent.MOUSE_MOVED:
- default:
- break;
- case MouseEvent.MOUSE_ENTERED:
- setCursor(
- isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
- break;
- case MouseEvent.MOUSE_EXITED:
- if (!myDragging) {
- setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- }
- break;
- case MouseEvent.MOUSE_PRESSED:
- setCursor(
- isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
- break;
- case MouseEvent.MOUSE_RELEASED:
- myDragging = false;
- myLastPoint = null;
- break;
- case MouseEvent.MOUSE_CLICKED:
- break;
- }
- }
-
- private final class DividerBorder implements Border {
- @Override
- public final void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) {
- final ToolWindowAnchor anchor = myInfo.getAnchor();
- final boolean isVertical = !anchor.isSplitVertically();
- final JBColor outer = new JBColor(Color.white, Color.darkGray);
- if (isVertical) {
- if (anchor == ToolWindowAnchor.TOP) {
- g.setColor(outer);
- UIUtil.drawLine(g, x, y, x + width - 1, y);
- g.setColor(Color.darkGray);
- UIUtil.drawLine(g, x, y + height - 1, x + width - 1, y + height - 1);
- }
- else {
- g.setColor(Color.darkGray);
- UIUtil.drawLine(g, x, y, x + width - 1, y);
- g.setColor(outer);
- UIUtil.drawLine(g, x, y + height - 1, x + width - 1, y + height - 1);
- }
- }
- else {
- if (anchor == ToolWindowAnchor.LEFT) {
- g.setColor(outer);
- UIUtil.drawLine(g, x, y, x, y + height - 1);
- g.setColor(Color.darkGray);
- UIUtil.drawLine(g, x + width - 1, y, x + width - 1, y + height - 1);
- }
- else {
- g.setColor(Color.darkGray);
- UIUtil.drawLine(g, x, y, x, y + height - 1);
- g.setColor(outer);
- UIUtil.drawLine(g, x + width - 1, y, x + width - 1, y + height - 1);
- }
- }
- }
-
- @Override
- public final Insets getBorderInsets(final Component c) {
- if (c instanceof MyDivider) {
- return new Insets(1, 1, 1, 1);
- }
- return new Insets(0, 0, 0, 0);
- }
-
- @Override
- public final boolean isBorderOpaque() {
- return true;
- }
+ return isVerticalCursor ? Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java
index 19131753b5ba..e1824f775e82 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java
@@ -67,7 +67,6 @@ import java.util.Set;
*/
@State(
name = "WindowManager",
- roamingType = RoamingType.GLOBAL,
storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/window.manager.xml")})
public final class WindowManagerImpl extends WindowManagerEx implements NamedComponent, PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowManagerImpl");
diff --git a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java
index b7704a687441..6099561c7283 100644
--- a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java
@@ -16,6 +16,7 @@
package com.intellij.ui;
import com.intellij.openapi.util.Pair;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -105,8 +106,11 @@ public class TableExpandableItemsHandler extends AbstractExpandableItemsHandler<
return myComponent.getCellRect(tableCellKey.row, tableCellKey.column, false);
}
+ @Nullable
public Pair<Component, Rectangle> getCellRendererAndBounds(TableCell key) {
- if (key.row < 0 || key.row >= myComponent.getRowCount() || key.column < 0 || key.column >= myComponent.getColumnCount()) {
+ if (key.row < 0 || key.row >= myComponent.getRowCount() ||
+ key.column < 0 || key.column >= myComponent.getColumnCount() ||
+ key.row == myComponent.getEditingRow() && key.column == myComponent.getEditingColumn()) {
return null;
}
diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
index d0b110f083bf..2d8bffe98d04 100644
--- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
@@ -33,9 +33,8 @@ import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.content.*;
import com.intellij.ui.switcher.SwitchProvider;
import com.intellij.ui.switcher.SwitchTarget;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.SmartList;
-
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -191,7 +190,11 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
private void doAddContent(@NotNull final Content content, final int index) {
ApplicationManager.getApplication().assertIsDispatchThread();
- if (myContents.contains(content)) return;
+ if (myContents.contains(content)) {
+ myContents.remove(content);
+ myContents.add(index == -1 ? myContents.size() : index, content);
+ return;
+ }
((ContentImpl)content).setManager(this);
final int insertIndex = index == -1 ? myContents.size() : index;
@@ -703,6 +706,7 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
myContentWithChangedComponent.clear();
myUI = null;
myListeners.clear();
+ dataProviders.clear();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java
index ee586418dbd6..37646a19292f 100644
--- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.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.
@@ -94,6 +94,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
myProject = project;
}
+ @Override
public void register(final DockContainer container) {
myContainers.add(container);
Disposer.register(container, new Disposable() {
@@ -147,6 +148,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
return wnd != null ? key + "#" + wnd.myId : key;
}
+ @Override
public DockContainer getContainerFor(Component c) {
if (c == null) return null;
@@ -401,7 +403,8 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
});
}
- public Pair<FileEditor[], FileEditorProvider[]> createNewDockContainerFor(@NotNull VirtualFile file, FileEditorManagerImpl fileEditorManager) {
+ @NotNull
+ public Pair<FileEditor[], FileEditorProvider[]> createNewDockContainerFor(@NotNull VirtualFile file, @NotNull FileEditorManagerImpl fileEditorManager) {
DockContainer container = getFactory(DockableEditorContainerFactory.TYPE).createContainer(null);
register(container);
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java
index 2a70b61c6e8a..47ebb829adc2 100644
--- a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java
+++ b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java
@@ -190,7 +190,7 @@ public class JBMacMessages extends MacMessagesEmulation {
SheetMessage sheetMessage = new SheetMessage(window, title, message, UIUtil.getQuestionIcon(),
new String [] {yesButton, noButton}, doNotAskDialogOption, yesButton, noButton);
int result = sheetMessage.getResult().equals(yesButton) ? Messages.YES : Messages.NO;
- if (doNotAskDialogOption != null) {
+ if (doNotAskDialogOption != null && (result == Messages.YES || doNotAskDialogOption.shouldSaveOptionsOnCancel())) {
doNotAskDialogOption.setToBeShown(sheetMessage.toBeShown(), result);
}
return result;
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
index 1b9190f6a740..d8b512367f26 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java
@@ -189,7 +189,7 @@ public abstract class WizardPopup extends AbstractPopup implements ActionListene
targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING;
}
} else {
- ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(aScreenX, aScreenY), null);
+ ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(aScreenX + 1, aScreenY + 1), null);
}
if (getParent() == null) {
diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java
index 9561c77b02d6..3ece5a6b77cd 100644
--- a/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java
+++ b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java
@@ -17,6 +17,7 @@ package com.intellij.ui.win;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.diff.ApplicationStarterBase;
+import org.jetbrains.annotations.Nullable;
/**
@@ -33,7 +34,7 @@ public class RecentProjectApplication extends ApplicationStarterBase {
}
@Override
- protected void processCommand(String[] args) throws Exception {
+ protected void processCommand(String[] args, @Nullable String currentDirectory) throws Exception {
ProjectUtil.openProject(args[1], null, false);
}
} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java
index 60c5f90c8b73..bd0efda42c48 100644
--- a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java
+++ b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java
@@ -22,6 +22,7 @@ import com.intellij.ui.EditorTextField;
import com.intellij.ui.components.OrphanGuardian;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FilteringIterator;
+import com.intellij.util.ui.JBSwingUtilities;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntStack;
import org.jetbrains.annotations.NotNull;
@@ -34,7 +35,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
-public class IJSwingUtilities {
+public class IJSwingUtilities extends JBSwingUtilities {
public static void invoke(Runnable runnable) {
if (ApplicationManager.getApplication().isDispatchThread()) {
runnable.run();