diff options
Diffstat (limited to 'platform/platform-impl/src/com')
109 files changed, 1892 insertions, 1107 deletions
diff --git a/platform/platform-impl/src/com/intellij/codeStyle/DefaultCodeStyleFacade.java b/platform/platform-impl/src/com/intellij/codeStyle/DefaultCodeStyleFacade.java index bf748ab945ba..4d9a34a029b5 100644 --- a/platform/platform-impl/src/com/intellij/codeStyle/DefaultCodeStyleFacade.java +++ b/platform/platform-impl/src/com/intellij/codeStyle/DefaultCodeStyleFacade.java @@ -19,6 +19,7 @@ */ package com.intellij.codeStyle; +import com.intellij.lang.Language; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.options.Configurable; @@ -39,7 +40,7 @@ public class DefaultCodeStyleFacade extends CodeStyleFacade { return "\n"; } - public int getRightMargin() { + public int getRightMargin(Language language) { return 80; } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/PerformanceWatcher.java b/platform/platform-impl/src/com/intellij/diagnostic/PerformanceWatcher.java index 88d3aa285960..26a6f6356d2a 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/PerformanceWatcher.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/PerformanceWatcher.java @@ -45,7 +45,7 @@ public class PerformanceWatcher implements ApplicationComponent { private ThreadMXBean myThreadMXBean; private final DateFormat myDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss"); //private DateFormat myPrintDateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); - private File myLogDir; + private File mySessionLogDir; private int myUnresponsiveDuration = 0; private File myCurHangLogDir; private List<StackTraceElement> myStacktraceCommonPart; @@ -98,9 +98,9 @@ public class PerformanceWatcher implements ApplicationComponent { } }); - myLogDir = new File(PathManager.getLogPath() + "/threadDumps-" + myDateFormat.format(new Date()) + mySessionLogDir = new File(PathManager.getLogPath() + "/threadDumps-" + myDateFormat.format(new Date()) + "-" + ApplicationInfo.getInstance().getBuild().asString()); - myCurHangLogDir = myLogDir; + myCurHangLogDir = mySessionLogDir; try { myShutdownSemaphore.acquire(); @@ -164,22 +164,22 @@ public class PerformanceWatcher implements ApplicationComponent { } if (mySwingThreadCounter != myLoopCounter) { myUnresponsiveDuration += UNRESPONSIVE_INTERVAL; - if (myUnresponsiveDuration == UNRESPONSIVE_THRESHOLD) { - //System.out.println("EDT is not responding at " + myPrintDateFormat.format(new Date())); - myCurHangLogDir = new File(myLogDir, myDateFormat.format(new Date())); - } if (myUnresponsiveDuration >= UNRESPONSIVE_THRESHOLD) { + if (myCurHangLogDir == mySessionLogDir) { + //System.out.println("EDT is not responding at " + myPrintDateFormat.format(new Date())); + myCurHangLogDir = new File(mySessionLogDir, myDateFormat.format(new Date())); + } dumpThreads(false); } } else { if (myUnresponsiveDuration >= UNRESPONSIVE_THRESHOLD) { //System.out.println("EDT was unresponsive for " + myUnresponsiveDuration + " seconds"); - if (myCurHangLogDir.exists()) { - myCurHangLogDir.renameTo(new File(myLogDir, getLogDirForHang())); + if (myCurHangLogDir != mySessionLogDir && myCurHangLogDir.exists()) { + myCurHangLogDir.renameTo(new File(mySessionLogDir, getLogDirForHang())); } myUnresponsiveDuration = 0; - myCurHangLogDir = myLogDir; + myCurHangLogDir = mySessionLogDir; myStacktraceCommonPart = null; } diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index 26429fc0e896..d263288634b7 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -181,7 +181,8 @@ public class EditorHyperlinkSupport { new FilteringProcessor<RangeHighlighterEx>(new Condition<RangeHighlighterEx>() { @Override public boolean value(RangeHighlighterEx rangeHighlighterEx) { - return HYPERLINK_LAYER == rangeHighlighterEx.getLayer() && + return rangeHighlighterEx.getEditorFilter().avaliableIn(editor) && + HYPERLINK_LAYER == rangeHighlighterEx.getLayer() && rangeHighlighterEx.isValid() && getHyperlinkInfo(rangeHighlighterEx) != null; } diff --git a/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.java b/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.java index acd74f9c8f54..f38ef84a2b93 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.java +++ b/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.java @@ -23,9 +23,11 @@ import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.ex.KeymapManagerEx; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import gnu.trove.THashSet; import java.io.File; import java.io.IOException; +import java.util.Set; /** * @author Konstantin Bulenkov @@ -47,13 +49,20 @@ public class KeymapGenerator implements ApplicationStarter { xml.append("<Keymaps>\n"); for (Keymap keymap : KeymapManagerEx.getInstanceEx().getAllKeymaps()) { - xml.append(" <Keymap name=\"").append(keymap.getName()).append("\">\n"); + + xml.append(" <Keymap name=\"").append(keymap.getPresentableName()).append("\">\n"); for (String id : keymap.getActionIds()) { String shortcuts = KeymapUtil.getShortcutsText(keymap.getShortcuts(id)); if (!StringUtil.isEmpty(shortcuts)) { xml.append(" <Action id=\"").append(id).append("\">\n"); + Set<String> addedShortcuts = new THashSet<String>(); for (Shortcut shortcut : keymap.getShortcuts(id)) { - xml.append(" <Shortcut>").append(KeymapUtil.getShortcutText(shortcut)).append("</Shortcut>\n"); + // Different shortcuts may have equal display strings (e.g. shift+minus and shift+subtract) + // We don't want them do be duplicated for users + String shortcutText = KeymapUtil.getShortcutText(shortcut); + if (addedShortcuts.add(shortcutText)) { + xml.append(" <Shortcut>").append(shortcutText).append("</Shortcut>\n"); + } } xml.append(" </Action>\n"); } diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index e92f80ffc95c..1bbd74984fcc 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -44,6 +44,7 @@ import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.UIUtil; +import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,6 +54,7 @@ import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.List; @@ -731,9 +733,29 @@ public class IdeEventQueue extends EventQueue { } } + private static Field stickyAltField; //IDEA-17359 private static void fixStickyAlt(AWTEvent e) { - if (SystemInfo.isWindowsXP && e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT) { + if (Registry.is("actionSystem.win.suppressAlt.new")) { + if (SystemInfo.isWindows + && UIManager.getLookAndFeel() instanceof WindowsLookAndFeel + && e instanceof InputEvent + && (((InputEvent)e).getModifiers() & (InputEvent.ALT_MASK | InputEvent.ALT_DOWN_MASK)) != 0 + && !(e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT)) { + try { + if (stickyAltField == null) { + stickyAltField = Class + .forName("com.sun.java.swing.plaf.windows.WindowsRootPaneUI$AltProcessor") + .getDeclaredField("menuCanceledOnPress"); + stickyAltField.setAccessible(true); + } + stickyAltField.set(null, true); + } + catch (Exception exception) { + LOG.error(exception); + } + } + } else if (SystemInfo.isWindowsXP && e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT) { ((KeyEvent)e).consume(); } } @@ -940,7 +962,7 @@ public class IdeEventQueue extends EventQueue { @Override public boolean dispatch(AWTEvent e) { boolean dispatch = true; - if (e instanceof KeyEvent) { + if (!Registry.is("actionSystem.win.suppressAlt.new") && e instanceof KeyEvent) { KeyEvent ke = (KeyEvent)e; final Component component = ke.getComponent(); final Window window = component == null ? null : SwingUtilities.windowForComponent(component); diff --git a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java index 798c029e01a8..a90d0df033ff 100644 --- a/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/MacOSApplicationProvider.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. @@ -28,8 +28,6 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.options.ex.IdeConfigurablesGroup; -import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.SystemInfo; @@ -98,8 +96,7 @@ public class MacOSApplicationProvider implements ApplicationComponent { } if (!((ShowSettingsUtilImpl)ShowSettingsUtil.getInstance()).isAlreadyShown()) { - ShowSettingsUtil.getInstance().showSettingsDialog(project, new ProjectConfigurablesGroup(project), - new IdeConfigurablesGroup()); + ShowSettingsUtil.getInstance().showSettingsDialog(project, ShowSettingsUtilImpl.getConfigurableGroups(project, true)); } applicationEvent.setHandled(true); } diff --git a/platform/platform-impl/src/com/intellij/ide/TipOfTheDayManager.java b/platform/platform-impl/src/com/intellij/ide/TipOfTheDayManager.java index 3c510c0a7ac8..a93fea76ca67 100644 --- a/platform/platform-impl/src/com/intellij/ide/TipOfTheDayManager.java +++ b/platform/platform-impl/src/com/intellij/ide/TipOfTheDayManager.java @@ -39,7 +39,7 @@ public class TipOfTheDayManager implements StartupActivity, DumbAware { ToolWindowManager.getInstance(project).invokeLater(new Runnable() { public void run() { if (project.isDisposed()) return; - new TipDialog().show(); + TipDialog.createForProject(project).show(); } }); } 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 e89a7a328b28..eda6ec9f2d7c 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsAction.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,8 +20,6 @@ import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.options.ex.IdeConfigurablesGroup; -import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; @@ -60,7 +58,6 @@ public class ShowSettingsAction extends AnAction implements DumbAware { } } }); - ShowSettingsUtil.getInstance().showSettingsDialog(project, new ProjectConfigurablesGroup(project), - new IdeConfigurablesGroup()); + ShowSettingsUtil.getInstance().showSettingsDialog(project, ShowSettingsUtilImpl.getConfigurableGroups(project, true)); } } 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 7e31726d5f97..4df11f7261ca 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowSettingsUtilImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.options.ex.ConfigurableExtensionPointUtil; import com.intellij.openapi.options.ex.IdeConfigurablesGroup; +import com.intellij.openapi.options.ex.MixedConfigurableGroup; import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.options.ex.SingleConfigurableEditor; import com.intellij.openapi.options.newEditor.OptionsEditor; @@ -29,6 +30,7 @@ import com.intellij.openapi.options.newEditor.OptionsEditorDialog; import com.intellij.openapi.options.newEditor.PreferencesDialog; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ui.update.Activatable; import com.intellij.util.ui.update.UiNotifyConnector; @@ -47,11 +49,62 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.ShowSettingsUtilImpl"); private AtomicBoolean myShown = new AtomicBoolean(false); + @NotNull + private static Project getProject(@Nullable Project project) { + return project != null ? project : ProjectManager.getInstance().getDefaultProject(); + } + + @NotNull + private static DialogWrapper getDialog(@Nullable Project project, @NotNull ConfigurableGroup[] groups, @Nullable Configurable toSelect) { + return Registry.is("ide.perProjectModality") + ? new OptionsEditorDialog(getProject(project), filterEmptyGroups(groups), toSelect, true) + : Registry.is("ide.new.preferences") + ? new PreferencesDialog(getProject(project), filterEmptyGroups(groups)) + : new OptionsEditorDialog(getProject(project), filterEmptyGroups(groups), toSelect); + } + + @NotNull + public static ConfigurableGroup[] getConfigurableGroups(@Nullable Project project, boolean withIdeSettings) { + ConfigurableGroup[] groups = !withIdeSettings + ? new ConfigurableGroup[]{new ProjectConfigurablesGroup(getProject(project))} + : (project == null) + ? new ConfigurableGroup[]{new IdeConfigurablesGroup()} + : new ConfigurableGroup[]{ + new ProjectConfigurablesGroup(project), + new IdeConfigurablesGroup()}; + + return Registry.is("ide.file.settings.order.new") + ? MixedConfigurableGroup.getGroups(getConfigurables(groups, true)) + : groups; + } + + @NotNull + public static Configurable[] getConfigurables(@Nullable Project project, boolean withGroupReverseOrder) { + return getConfigurables(getConfigurableGroups(project, true), withGroupReverseOrder); + } + + @NotNull + private static Configurable[] getConfigurables(@NotNull ConfigurableGroup[] groups, boolean withGroupReverseOrder) { + Configurable[][] arrays = new Configurable[groups.length][]; + int length = 0; + for (int i = 0; i < groups.length; i++) { + arrays[i] = groups[withGroupReverseOrder ? groups.length - 1 - i : i].getConfigurables(); + length += arrays[i].length; + } + Configurable[] configurables = new Configurable[length]; + int offset = 0; + for (Configurable[] array : arrays) { + System.arraycopy(array, 0, configurables, offset, array.length); + offset += array.length; + } + return configurables; + } + @Override public void showSettingsDialog(@NotNull Project project, @NotNull ConfigurableGroup[] group) { try { myShown.set(true); - _showSettingsDialog(project, group, null); + getDialog(project, group, null).show(); } catch (Exception e) { LOG.error(e); @@ -61,41 +114,17 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { } } - private static void _showSettingsDialog(@NotNull final Project project, @NotNull ConfigurableGroup[] group, @Nullable Configurable toSelect) { - group = filterEmptyGroups(group); - if (Registry.is("ide.perProjectModality")) { - new OptionsEditorDialog(project, group, toSelect, true).show(); - } else { - if (Registry.is("ide.new.preferences")) { - new PreferencesDialog(project, group).show(); - } else { - new OptionsEditorDialog(project, group, toSelect).show(); - } - } - } - @Override public void showSettingsDialog(@Nullable final Project project, final Class configurableClass) { assert Configurable.class.isAssignableFrom(configurableClass) : "Not a configurable: " + configurableClass.getName(); - ConfigurableGroup[] groups; - IdeConfigurablesGroup commonGroup = new IdeConfigurablesGroup(); - ProjectConfigurablesGroup projectGroup = project == null ? null : new ProjectConfigurablesGroup(project); - if (projectGroup == null) { - groups = new ConfigurableGroup[] {commonGroup}; - } else { - groups = new ConfigurableGroup[] {projectGroup, commonGroup}; - } + ConfigurableGroup[] groups = getConfigurableGroups(project, true); - Configurable config = findByClass(commonGroup.getConfigurables(), configurableClass); - if (config == null && projectGroup != null) { - config = findByClass(projectGroup.getConfigurables(), configurableClass); - } + Configurable config = findByClass(getConfigurables(groups, true), configurableClass); assert config != null : "Cannot find configurable: " + configurableClass.getName(); - @NotNull Project nnProject = project != null ? project : ProjectManager.getInstance().getDefaultProject(); - _showSettingsDialog(nnProject, groups, config); + getDialog(project, groups, config).show(); } @Nullable @@ -110,15 +139,9 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { @Override public void showSettingsDialog(@Nullable final Project project, @NotNull final String nameToSelect) { - ConfigurableGroup[] group; - if (project == null) { - group = new ConfigurableGroup[]{new IdeConfigurablesGroup()}; - } - else { - group = new ConfigurableGroup[]{new ProjectConfigurablesGroup(project), new IdeConfigurablesGroup()}; - } + ConfigurableGroup[] group = getConfigurableGroups(project, true); - Project actualProject = project != null ? project : ProjectManager.getInstance().getDefaultProject(); + Project actualProject = getProject(project); group = filterEmptyGroups(group); @@ -133,15 +156,9 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { } public static void showSettingsDialog(@Nullable Project project, final String id2Select, final String filter) { - ConfigurableGroup[] group; - if (project == null) { - group = new ConfigurableGroup[]{new IdeConfigurablesGroup()}; - } - else { - group = new ConfigurableGroup[]{new ProjectConfigurablesGroup(project), new IdeConfigurablesGroup()}; - } + ConfigurableGroup[] group = getConfigurableGroups(project, true); - Project actualProject = project != null ? project : ProjectManager.getInstance().getDefaultProject(); + Project actualProject = getProject(project); group = filterEmptyGroups(group); final Configurable configurable2Select = findConfigurable2Select(id2Select, group); @@ -191,10 +208,7 @@ public class ShowSettingsUtilImpl extends ShowSettingsUtil { @Override public void showSettingsDialog(@NotNull final Project project, final Configurable toSelect) { - _showSettingsDialog(project, new ConfigurableGroup[]{ - new ProjectConfigurablesGroup(project), - new IdeConfigurablesGroup() - }, toSelect); + getDialog(project, getConfigurableGroups(project, true), toSelect).show(); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TemplateProjectPropertiesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TemplateProjectPropertiesAction.java index 75657c517ecb..6c2b7d8e62f6 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/TemplateProjectPropertiesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/TemplateProjectPropertiesAction.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,7 +18,6 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectManagerEx; @@ -26,6 +25,6 @@ import com.intellij.openapi.project.ex.ProjectManagerEx; public class TemplateProjectPropertiesAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { Project defaultProject = ProjectManagerEx.getInstanceEx().getDefaultProject(); - ShowSettingsUtil.getInstance().showSettingsDialog(defaultProject, new ProjectConfigurablesGroup(defaultProject)); + ShowSettingsUtil.getInstance().showSettingsDialog(defaultProject, ShowSettingsUtilImpl.getConfigurableGroups(defaultProject, false)); } } diff --git a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java index de154f249c9e..930901d55105 100644 --- a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java +++ b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java @@ -17,6 +17,7 @@ package com.intellij.ide.customize; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.ide.plugins.RepositoryHelper; import com.intellij.idea.StartupUtil; import com.intellij.openapi.application.PathManager; @@ -58,14 +59,14 @@ class PluginGroups { } private PluginGroups() { - myAllPlugins = PluginManager.loadDescriptors(null); + myAllPlugins = PluginManagerCore.loadDescriptors(null); try { myPluginsFromRepository.addAll(RepositoryHelper.loadPluginsFromRepository(null)); } catch (Exception e) { //OK, it's offline } - PluginManager.loadDisabledPlugins(new File(PathManager.getConfigPath()).getPath(), myDisabledPluginIds); + PluginManagerCore.loadDisabledPlugins(new File(PathManager.getConfigPath()).getPath(), myDisabledPluginIds); myTree.put(CORE, Pair.create((String)null, Arrays.asList( @@ -74,7 +75,6 @@ class PluginGroups { "org.intellij.intelliLang", "com.intellij.properties", "Refactor-X",//? - "Structural Search", "Type Migration", "ZKM" ))); diff --git a/platform/platform-impl/src/com/intellij/ide/file/BatchFileChangeListener.java b/platform/platform-impl/src/com/intellij/ide/file/BatchFileChangeListener.java new file mode 100644 index 000000000000..593c39885a46 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/file/BatchFileChangeListener.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.file; + +import com.intellij.openapi.project.Project; +import com.intellij.util.messages.Topic; + +/** + * This listener is notified when some operation performs a massive batch file change, and when this change is completed. + * <p/> + * To subscribe to such batch file changes, connect to the Project's {@link com.intellij.util.messages.MessageBus} + * via the {@link #TOPIC} defined below. + */ +public interface BatchFileChangeListener { + + Topic<BatchFileChangeListener> TOPIC = Topic.create("Batch File Update", BatchFileChangeListener.class); + + class Adapter implements BatchFileChangeListener { + @Override + public void batchChangeStarted(Project project) { + } + @Override + public void batchChangeCompleted(Project project) { + } + } + + + void batchChangeStarted(Project project); + + void batchChangeCompleted(Project project); + +} diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/HelpID.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/HelpID.java index b05021ff7d72..a805638501be 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/HelpID.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/HelpID.java @@ -24,6 +24,8 @@ import org.jetbrains.annotations.NonNls; * Time: 2:09 PM */ public interface HelpID { - @NonNls String RESET_PASSWORD = "reference_ide_settings_master_password_reset"; - @NonNls String CHANGE_PASSWORD = "reference_settings_password_safe_master_password"; + @NonNls String INIT_PASSWORD = "settings_passwords_master_password_init"; + @NonNls String ENTER_PASSWORD = "settings_passwords_master_password_enter"; + @NonNls String RESET_PASSWORD = "settings_passwords_master_password_reset"; + @NonNls String CHANGE_PASSWORD = "settings_passwords_master_password_change"; } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java index b1ea1332986e..e5b9f1530256 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java @@ -25,15 +25,21 @@ import org.jetbrains.annotations.Nullable; * The interface defines basic password management operations */ public interface PasswordStorage { + /** - * <p>Get password stored in a password safe.</p> - * - * <p><b>NB: </b> - * This method may be called from the background, - * and it may need to ask user to enter the master password to access the database by calling - * {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()} to show a modal dialog. - * So make sure not to call it from the read action. - * Calling this method from the dispatch thread is allowed.</p> + * @deprecated To remove in IDEA 15. Use {@link #getPassword(Project, Class, String, ModalityState)} + */ + @Deprecated + @Nullable + String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException; + + /** + * Get password stored in a password safe. + * <p/> + * The method may be called from any thread. It may need to show a master password dialog to unlock the password database, + * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}. + * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress + * windows. * * @param project the project, that is used to ask for the master password if this is the first access to password safe * @param requestor the requestor class @@ -43,25 +49,53 @@ public interface PasswordStorage { * @throws IllegalStateException if the method is called from the read action. */ @Nullable - String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException; + String getPassword(@Nullable Project project, @NotNull Class requestor, String key, + @Nullable ModalityState state) throws PasswordSafeException; + /** - * Remove password stored in a password safe + * Store password in password safe + * <p/> + * The method may be called from any thread. It may need to show a master password dialog to unlock the password database, + * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}. + * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress + * windows. * * @param project the project, that is used to ask for the master password if this is the first access to password safe * @param requestor the requestor class * @param key the key for the password - * @return the plugin key + * @param value the value to store * @throws PasswordSafeException if password safe cannot be accessed */ + void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value, + @Nullable ModalityState modalityState) throws PasswordSafeException; + + /** + * @deprecated To remove in IDEA 15. Use {@link #storePassword(Project, Class, String, String, ModalityState)} + */ + @Deprecated + void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException; + + /** + * @deprecated To remove in IDEA 15. Use {@link #removePassword(Project, Class, String, ModalityState)} + */ + @Deprecated void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException; + /** - * Store password in password safe + * Remove password stored in a password safe + * <p/> + * The method may be called from any thread. It may need to show a master password dialog to unlock the password database, + * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}. + * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress + * windows. * * @param project the project, that is used to ask for the master password if this is the first access to password safe * @param requestor the requestor class * @param key the key for the password - * @param value the value to store + * @return the plugin key * @throws PasswordSafeException if password safe cannot be accessed */ - void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException; + void removePassword(@Nullable Project project, @NotNull Class requestor, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException; + } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java index 11dc4d7d018b..34aee7aaad38 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java @@ -22,42 +22,19 @@ import com.intellij.ide.passwordSafe.impl.providers.masterKey.MasterKeyPasswordS import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase; import com.intellij.ide.passwordSafe.impl.providers.memory.MemoryPasswordSafe; import com.intellij.ide.passwordSafe.impl.providers.nil.NilProvider; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * The implementation of password safe service - */ public class PasswordSafeImpl extends PasswordSafe { - /** - * The logger instance - */ private static final Logger LOG = Logger.getInstance(PasswordSafeImpl.class.getName()); - /** - * The current settings - */ private final PasswordSafeSettings mySettings; - /** - * The master key provider - */ private final MasterKeyPasswordSafe myMasterKeyProvider; - /** - * The nil provider - */ private final NilProvider myNilProvider; - /** - * The memory provider - */ private final MemoryPasswordSafe myMemoryProvider; - /** - * The constructor - * - * @param settings the settings for the password safe - * @param database the password database - */ public PasswordSafeImpl(PasswordSafeSettings settings, PasswordDatabase database) { mySettings = settings; myMasterKeyProvider = new MasterKeyPasswordSafe(database); @@ -89,21 +66,24 @@ public class PasswordSafeImpl extends PasswordSafe { return p; } - - /** - * @return settings for the passwords safe - */ public PasswordSafeSettings getSettings() { return mySettings; } - @Nullable + @Override public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { + return getPassword(project, requester, key, null); + } + + @Nullable + @Override + public String getPassword(@Nullable Project project, @NotNull Class requester, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) { - String password = getMemoryProvider().getPassword(project, requester, key); + String password = getMemoryProvider().getPassword(project, requester, key, modalityState); if (password == null) { - password = provider().getPassword(project, requester, key); + password = provider().getPassword(project, requester, key, modalityState); if (password != null) { // cache the password in memory as well for easier access during the session getMemoryProvider().storePassword(project, requester, key, password); @@ -111,27 +91,35 @@ public class PasswordSafeImpl extends PasswordSafe { } return password; } - return provider().getPassword(project, requester, key); + return provider().getPassword(project, requester, key, modalityState); } - /** - * {@inheritDoc} - */ - public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { + @Override + public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { + removePassword(project, requestor, key, null); + } + + @Override + public void removePassword(@Nullable Project project, @NotNull Class requester, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) { getMemoryProvider().removePassword(project, requester, key); } - provider().removePassword(project, requester, key); + provider().removePassword(project, requester, key, modalityState); } - /** - * {@inheritDoc} - */ - public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException { + @Override + public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException { + storePassword(project, requestor, key, value, null); + } + + @Override + public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value, + @Nullable ModalityState modalityState) throws PasswordSafeException { if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) { getMemoryProvider().storePassword(project, requester, key, value); } - provider().storePassword(project, requester, key, value); + provider().storePassword(project, requester, key, value, modalityState); } /** diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java index 18dee7c755f5..3a40d617e99b 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java @@ -15,7 +15,11 @@ */ package com.intellij.ide.passwordSafe.impl; +import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.PasswordStorage; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * The provider for password safe component @@ -34,4 +38,21 @@ public abstract class PasswordSafeProvider implements PasswordStorage { * @return the name of provider */ public abstract String getName(); + + @Nullable + @Override + public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { + return getPassword(project, requestor, key, null); + } + + @Override + public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException { + storePassword(project, requestor, key, value, null); + } + + @Override + public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { + removePassword(project, requestor, key, null); + } + } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java index c72c65d0d528..8c8f921f18b8 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java @@ -43,16 +43,15 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider { * @throws PasswordSafeException in case of problems with access to the password database. * @throws IllegalStateException if the method is called from the read action. */ - protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException; + protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor, + @Nullable ModalityState modalityState) throws PasswordSafeException; - /** - * {@inheritDoc} - */ @Nullable - public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { - byte[] k = dbKey(project, requestor, key); + public String getPassword(@Nullable Project project, @NotNull Class requestor, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { + byte[] k = dbKey(project, requestor, key, modalityState); byte[] ct = getEncryptedPassword(k); - return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor), ct); + return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor, modalityState), ct); } /** @@ -69,17 +68,17 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider { * @param project * @param requestor the requestor class * @param key the key to use + * @param modalityState * @return the key to use for map */ - private byte[] dbKey(@Nullable Project project, Class requestor, String key) throws PasswordSafeException { - return EncryptionUtil.dbKey(key(project, requestor), requestor, key); + private byte[] dbKey(@Nullable Project project, @NotNull Class requestor, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { + return EncryptionUtil.dbKey(key(project, requestor, modalityState), requestor, key); } - /** - * {@inheritDoc} - */ - public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { - byte[] k = dbKey(project, requester, key); + public void removePassword(@Nullable Project project, @NotNull Class requester, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { + byte[] k = dbKey(project, requester, key, modalityState); removeEncryptedPassword(k); } @@ -90,12 +89,10 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider { */ protected abstract void removeEncryptedPassword(byte[] key); - /** - * {@inheritDoc} - */ - public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException { - byte[] k = dbKey(project, requestor, key); - byte[] ct = EncryptionUtil.encryptText(key(project, requestor), value); + public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value, + @Nullable ModalityState modalityState) throws PasswordSafeException { + byte[] k = dbKey(project, requestor, key, modalityState); + byte[] ct = EncryptionUtil.encryptText(key(project, requestor, modalityState), value); storeEncryptedPassword(k, ct); } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java index 638e2e23c1f9..304b31e3bee1 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/EnterPasswordComponent.java @@ -16,6 +16,7 @@ package com.intellij.ide.passwordSafe.impl.providers.masterKey; import com.intellij.ide.TypePresentationService; +import com.intellij.ide.passwordSafe.HelpID; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -46,4 +47,9 @@ public class EnterPasswordComponent extends PasswordComponentBase { String password = new String(myPasswordField.getPassword()); return mySafe.changeMasterPassword(password, password, myEncryptCheckBox.isSelected()); } + + @Override + public String getHelpId() { + return HelpID.ENTER_PASSWORD; + } } 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 95fba48afabe..b74e51315cd5 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 @@ -42,17 +42,8 @@ import java.util.concurrent.atomic.AtomicReference; * The password safe that stores information in configuration file encrypted by master password */ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { - /** - * The test password key - */ private static final String TEST_PASSWORD_KEY = "TEST_PASSWORD:"; - /** - * The test password value - */ private static final String TEST_PASSWORD_VALUE = "test password"; - /** - * The password database instance - */ final PasswordDatabase database; /** * The key to use to encrypt data @@ -68,18 +59,10 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } }; - /** - * The constructor - * - * @param database the password database - */ public MasterKeyPasswordSafe(PasswordDatabase database) { this.database = database; } - /** - * @return true if the component is running in the test mode - */ protected boolean isTestMode() { return false; } @@ -130,7 +113,6 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { else { return true; } - } /** @@ -167,18 +149,13 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } - /** - * The test key - * - * @param password the password for the test key - * @return the test key - */ private static String testKey(String password) { return TEST_PASSWORD_KEY + password; } @Override - protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException { + protected byte[] key(@Nullable final Project project, @NotNull final Class requestor, + @Nullable ModalityState modalityState) throws PasswordSafeException { Application application = ApplicationManager.getApplication(); if (!isTestMode() && application.isHeadlessEnvironment()) { throw new MasterPasswordUnavailableException("The provider is not available in headless environment"); @@ -223,7 +200,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } } } - }, ModalityState.defaultModalityState()); + }, modalityState == null ? ModalityState.defaultModalityState() : modalityState); //noinspection ThrowableResultOfMethodCallIgnored if (ex.get() != null) { throw ex.get(); @@ -233,20 +210,15 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return result.get(); } - /** - * {@inheritDoc} - */ @Override - public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException { + public String getPassword(@Nullable Project project, @NotNull Class requestor, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { if (database.isEmpty()) { return null; } - return super.getPassword(project, requestor, key); + return super.getPassword(project, requestor, key, modalityState); } - /** - * {@inheritDoc} - */ @Override public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { if (database.isEmpty()) { @@ -255,50 +227,32 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { super.removePassword(project, requester, key); } - /** - * {@inheritDoc} - */ @Override protected byte[] getEncryptedPassword(byte[] key) { return database.get(key); } - /** - * {@inheritDoc} - */ @Override protected void removeEncryptedPassword(byte[] key) { database.remove(key); } - /** - * {@inheritDoc} - */ @Override protected void storeEncryptedPassword(byte[] key, byte[] encryptedPassword) { database.put(key, encryptedPassword); } - /** - * {@inheritDoc} - */ @Override public boolean isSupported() { return !ApplicationManager.getApplication().isHeadlessEnvironment(); } - /** - * {@inheritDoc} - */ @Override public String getDescription() { return "This provider stores passwords in IDEA config and uses master password to encrypt other passwords. " + "The passwords for the same resources are shared between different projects."; } - /** - * {@inheritDoc} - */ @Override public String getName() { return "Master Key PasswordSafe"; @@ -309,9 +263,6 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return setMasterPassword(""); } - /** - * @return true, if OS protected passwords are supported for the current platform - */ @SuppressWarnings({"MethodMayBeStatic"}) public boolean isOsProtectedPasswordSupported() { // TODO extension point needed? @@ -351,9 +302,6 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } } - /** - * @return true, if the password is currently encrypted in the database - */ public boolean isPasswordEncrypted() { if (!isOsProtectedPasswordSupported()) return false; @@ -361,9 +309,6 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { return i != null && i.length > 0; } - /** - * @return check if provider database is empty - */ public boolean isEmpty() { return database.isEmpty(); } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java index ce75bdb2165a..faa36c121ec9 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/ResetPasswordComponent.java @@ -49,7 +49,7 @@ public class ResetPasswordComponent extends PasswordComponentBase { @Override public String getHelpId() { - return HelpID.RESET_PASSWORD; + return myFirstTime ? HelpID.INIT_PASSWORD : HelpID.RESET_PASSWORD; } @Override diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java index 5be4a25df859..da82bb986fdb 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java @@ -19,10 +19,12 @@ import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed; import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider; import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper; import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.security.SecureRandom; import java.util.Collections; @@ -57,13 +59,8 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider { return Registry.intValue("passwordSafe.memorySafe.ttl"); } - /** - * @param project the project to use - * @param requestor - * @return the secret key used by provider - */ @Override - protected byte[] key(Project project, @NotNull Class requestor) { + protected byte[] key(Project project, @NotNull Class requestor, @Nullable ModalityState modalityState) { if (key.get() == null) { byte[] rnd = new byte[EncryptionUtil.SECRET_KEY_SIZE_BYTES * 16]; new SecureRandom().nextBytes(rnd); @@ -72,49 +69,31 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider { return key.get(); } - /** - * {@inheritDoc} - */ @Override protected byte[] getEncryptedPassword(byte[] key) { return database.get().get(new ByteArrayWrapper(key)); } - /** - * {@inheritDoc} - */ @Override protected void removeEncryptedPassword(byte[] key) { database.get().remove(new ByteArrayWrapper(key)); } - /** - * {@inheritDoc} - */ @Override protected void storeEncryptedPassword(byte[] key, byte[] encryptedPassword) { database.get().put(new ByteArrayWrapper(key), encryptedPassword); } - /** - * {@inheritDoc} - */ @Override public boolean isSupported() { return true; } - /** - * {@inheritDoc} - */ @Override public String getDescription() { return "Memory-based password safe provider. The passwords are stored only for the duration of IDEA process."; } - /** - * {@inheritDoc} - */ @Override public String getName() { return "Memory PasswordSafe"; diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java index 581df18ea317..e3a77325b06e 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java @@ -17,6 +17,7 @@ package com.intellij.ide.passwordSafe.impl.providers.nil; import com.intellij.ide.passwordSafe.PasswordSafeException; import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,49 +26,38 @@ import org.jetbrains.annotations.Nullable; * The most secure provider that does not store anything, so it cannot be cracked */ public final class NilProvider extends PasswordSafeProvider { - /** - * {@inheritDoc} - */ + @Override public boolean isSupported() { return true; } - /** - * {@inheritDoc} - */ @Override public String getDescription() { return "The provider that does not remembers password."; } - /** - * {@inheritDoc} - */ @Override public String getName() { return "Do not Store"; } - /** - * {@inheritDoc} - */ - public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { + @Nullable + public String getPassword(@Nullable Project project, @NotNull Class requester, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { // nothing is stored return null; } - /** - * {@inheritDoc} - */ - public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException { + @Override + public void removePassword(@Nullable Project project, @NotNull Class requester, String key, + @Nullable ModalityState modalityState) throws PasswordSafeException { // do nothing } - /** - * {@inheritDoc} - */ - public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException { + @Override + public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value, + @Nullable ModalityState modalityState) throws PasswordSafeException { // just forget about password } } diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java index def7aa96ce9b..353e836f3f33 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java @@ -176,7 +176,7 @@ public class PasswordSafePromptDialog extends DialogWrapper { ps.removePassword(project, requestor, key); } else { - String pw = ps.getPassword(project, requestor, key); + String pw = ps.getPassword(project, requestor, key, modalityState); if (pw != null) { return pw; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 7919d1f894d0..b093773bc0fb 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -159,33 +159,35 @@ public class PluginInstaller { } } - synchronized (myLock) { - PluginDownloader downloader = null; - final String repositoryName = pluginNode.getRepositoryName(); - if (repositoryName != null) { - try { - final Map<PluginId, PluginDownloader> downloaders = new HashMap<PluginId, PluginDownloader>(); - if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders)) { - return false; - } - downloader = downloaders.get(pluginNode.getPluginId()); - if (downloader == null) return false; - } - catch (Exception e) { + PluginDownloader downloader = null; + final String repositoryName = pluginNode.getRepositoryName(); + if (repositoryName != null) { + try { + final Map<PluginId, PluginDownloader> downloaders = new HashMap<PluginId, PluginDownloader>(); + if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders)) { return false; } + downloader = downloaders.get(pluginNode.getPluginId()); + if (downloader == null) return false; } - else { - downloader = PluginDownloader.createDownloader(pluginNode); + catch (Exception e) { + return false; } - if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { + } + else { + downloader = PluginDownloader.createDownloader(pluginNode); + } + + if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { + synchronized (myLock) { downloader.install(); - pluginNode.setStatus(PluginNode.STATUS_DOWNLOADED); - } - else { - return false; } + pluginNode.setStatus(PluginNode.STATUS_DOWNLOADED); + } + else { + return false; } + return true; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 49b20d27a585..20a41e3a886a 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -49,6 +49,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.speedSearch.SpeedSearchSupply; import com.intellij.util.concurrency.SwingWorker; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.UiNotifyConnector; @@ -663,7 +664,7 @@ public abstract class PluginManagerMain implements Disposable { app.restart(true); } else { - app.exit(true); + app.exit(false, true); } } }).notify(project); @@ -676,6 +677,7 @@ public abstract class PluginManagerMain implements Disposable { } public void filter() { + getPluginTable().putClientProperty(SpeedSearchSupply.SEARCH_QUERY_KEY, getFilter()); pluginsModel.filter(getFilter().toLowerCase()); TableUtil.ensureSelectionExists(getPluginTable()); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form index 2e09735db57f..1791089faf85 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form @@ -69,13 +69,11 @@ <size top="0" left="0" bottom="2" right="0"/> </border> <children> - <component id="a5e28" class="com.intellij.ui.components.JBLabel" binding="myName"> + <component id="edd99" class="com.intellij.ui.SimpleColoredComponent" binding="myName"> <constraints> <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> - <properties> - <text value="Plugin Name"/> - </properties> + <properties/> </component> </children> </grid> diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java index be7fd44fb7cc..c90306210856 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java @@ -23,10 +23,16 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; +import com.intellij.psi.codeStyle.NameUtil; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; +import com.intellij.ui.SimpleColoredComponent; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.speedSearch.SpeedSearchSupply; +import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.util.Function; import com.intellij.util.text.DateFormatUtil; +import com.intellij.util.text.Matcher; import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -40,7 +46,7 @@ import java.util.Set; * @author Konstantin Bulenkov */ public class PluginsTableRenderer extends DefaultTableCellRenderer { - private JLabel myName; + private SimpleColoredComponent myName; private JLabel myStatus; private RatesPanel myRating; private JLabel myDownloads; @@ -85,7 +91,23 @@ public class PluginsTableRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (myPluginDescriptor != null) { final PluginId pluginId = myPluginDescriptor.getPluginId(); - myName.setText(myPluginDescriptor.getName() + " "); + myName.clear(); + myName.setOpaque(false); + String pluginName = myPluginDescriptor.getName() + " "; + Object query = table.getClientProperty(SpeedSearchSupply.SEARCH_QUERY_KEY); + if (query instanceof String) { + String pattern = "*" + query; + Matcher matcher = NameUtil.buildMatcher(pattern, 0, true, true, pattern.toLowerCase().equals(pattern)); + SimpleTextAttributes attr = new SimpleTextAttributes(UIUtil.getListBackground(isSelected), + UIUtil.getListForeground(isSelected), + JBColor.RED, + SimpleTextAttributes.STYLE_PLAIN); + + SpeedSearchUtil.appendColoredFragmentForMatcher(pluginName, myName, attr, matcher, + UIUtil.getTableBackground(isSelected), true); + } else { + myName.append(pluginName); + } final Color fg = UIUtil.getTableForeground(isSelected); final Color bg = UIUtil.getTableBackground(isSelected); 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 0a7b70e07616..8febc9ad392a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,12 @@ package com.intellij.ide.ui.search; import com.intellij.application.options.SkipSelfSearchComponent; +import com.intellij.ide.actions.ShowSettingsUtilImpl; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableGroup; import com.intellij.openapi.options.MasterDetails; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ex.GlassPanel; -import com.intellij.openapi.options.ex.IdeConfigurablesGroup; -import com.intellij.openapi.options.ex.ProjectConfigurablesGroup; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; @@ -66,8 +65,7 @@ public class SearchUtil { } public static void processProjectConfigurables(Project project, HashMap<SearchableConfigurable, TreeSet<OptionDescription>> options) { - processConfigurables(new ProjectConfigurablesGroup(project).getConfigurables(), options); - processConfigurables(new IdeConfigurablesGroup().getConfigurables(), options); + processConfigurables(ShowSettingsUtilImpl.getConfigurables(project, false), options); } private static void processConfigurables(final Configurable[] configurables, diff --git a/platform/platform-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java b/platform/platform-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java deleted file mode 100644 index a743569b1798..000000000000 --- a/platform/platform-impl/src/com/intellij/ide/util/PropertiesComponentImpl.java +++ /dev/null @@ -1,112 +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.ide.util; - -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.util.text.StringUtil; -import org.jdom.Element; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class PropertiesComponentImpl extends PropertiesComponent implements PersistentStateComponent<Element> { - private final Map<String, String> myMap = new LinkedHashMap<String, String>(); - @NonNls private static final String ELEMENT_PROPERTY = "property"; - @NonNls private static final String ATTRIBUTE_NAME = "name"; - @NonNls private static final String ATTRIBUTE_VALUE = "value"; - - @NotNull - public String getComponentName() { - return "PropertiesComponent"; - } - - PropertiesComponentImpl() { - } - - @Override - public Element getState() { - Element parentNode = new Element("state"); - for (final String key : myMap.keySet()) { - String value = myMap.get(key); - if (value != null) { - Element element = new Element(ELEMENT_PROPERTY); - element.setAttribute(ATTRIBUTE_NAME, key); - element.setAttribute(ATTRIBUTE_VALUE, value); - parentNode.addContent(element); - } - } - return parentNode; - } - - @Override - public void loadState(final Element parentNode) { - myMap.clear(); - for (Element e : parentNode.getChildren(ELEMENT_PROPERTY)) { - String name = e.getAttributeValue(ATTRIBUTE_NAME); - if (name != null) { - myMap.put(name, e.getAttributeValue(ATTRIBUTE_VALUE)); - } - } - } - - @Override - public String getValue(String name) { - return myMap.get(name); - } - - @Override - public void setValue(String name, String value) { - myMap.put(name, value); - } - - @Override - public void setValue(@NotNull String name, @NotNull String value, @NotNull String defaultValue) { - if (value.equals(defaultValue)) { - myMap.remove(name); - } - else { - myMap.put(name, value); - } - } - - @Override - public void unsetValue(String name) { - myMap.remove(name); - } - - @Override - public boolean isValueSet(String name) { - return myMap.containsKey(name); - } - - @Override - public String[] getValues(@NonNls String name) { - final String value = getValue(name); - return value != null ? value.split("\n") : null; - } - - @Override - public void setValues(@NonNls String name, String[] values) { - if (values == null) { - setValue(name, null); - } - else { - setValue(name, StringUtil.join(values, "\n")); - } - } -}
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java index 33501b503477..0744e377e6c5 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java @@ -19,32 +19,44 @@ package com.intellij.ide.util; import com.intellij.CommonBundle; import com.intellij.ide.IdeBundle; import com.intellij.internal.statistic.UsageTrigger; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl; +import com.intellij.openapi.wm.ex.WindowManagerEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; public class TipDialog extends DialogWrapper{ - private final TipPanel myTipPanel; + private TipPanel myTipPanel; public TipDialog(){ - super(true); - setModal(false); - setTitle(IdeBundle.message("title.tip.of.the.day")); - setCancelButtonText(CommonBundle.getCloseButtonText()); - myTipPanel = new TipPanel(); - myTipPanel.nextTip(); - setHorizontalStretch(1.33f); - setVerticalStretch(1.25f); - init(); - if (getPeer() instanceof DialogWrapperPeerImpl) { - ((DialogWrapperPeerImpl)getPeer()).setAutoRequestFocus(false); - } + super(WindowManagerEx.getInstanceEx().findVisibleFrame(), true); + initialize(); + } + + public TipDialog(@NotNull final Window parent) { + super(parent, true); + initialize(); } + private void initialize () { + setModal(false); + setTitle(IdeBundle.message("title.tip.of.the.day")); + setCancelButtonText(CommonBundle.getCloseButtonText()); + myTipPanel = new TipPanel(); + myTipPanel.nextTip(); + setHorizontalStretch(1.33f); + setVerticalStretch(1.25f); + init(); + if (getPeer() instanceof DialogWrapperPeerImpl) { + ((DialogWrapperPeerImpl)getPeer()).setAutoRequestFocus(false); + } + } + @NotNull protected Action[] createActions(){ return new Action[]{new PreviousTipAction(),new NextTipAction(),getCancelAction()}; @@ -58,6 +70,11 @@ public class TipDialog extends DialogWrapper{ super.dispose(); } + public static TipDialog createForProject(final Project project) { + final Window w = WindowManagerEx.getInstanceEx().suggestParentWindow(project); + return (w == null) ? new TipDialog() : new TipDialog(w); + } + private class PreviousTipAction extends AbstractAction{ public PreviousTipAction(){ super(IdeBundle.message("action.previous.tip")); diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java b/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java index 3a8f73348640..67a7c0f88532 100644 --- a/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java +++ b/platform/platform-impl/src/com/intellij/idea/IdeaLogger.java @@ -199,7 +199,7 @@ public class IdeaLogger extends Logger { @Override public String getInfo() { final ApplicationInfoEx info = ApplicationInfoImpl.getShadowInstance(); - return info.getFullApplicationName() + " " + "Build #" + info.getBuild().asString(); + return info.getFullApplicationName() + " " + "Build #" + info.getBuild().asStringWithAllDetails(); } }; } diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index 54e81ab8458e..43c0a2d298f1 100755 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -320,7 +320,7 @@ public class StartupUtil { ApplicationInfo appInfo = ApplicationInfoImpl.getShadowInstance(); ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance(); String buildDate = new SimpleDateFormat("dd MMM yyyy HH:ss", Locale.US).format(appInfo.getBuildDate().getTime()); - log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild() + ", " + buildDate + ")"); + log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild().asStringWithAllDetails() + ", " + buildDate + ")"); log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ", " + SystemInfo.OS_ARCH + ")"); log.info("JRE: " + System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")"); log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")"); diff --git a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java index 72e7b8a4973e..a4d4637fa81d 100644 --- a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java @@ -37,15 +37,26 @@ public class JpsIdePluginManagerImpl extends JpsPluginManager { public JpsIdePluginManagerImpl() { ExtensionsArea rootArea = Extensions.getRootArea(); - //todo[nik] introduce more generic platform extension for JPS plugins instead + //todo[nik] get rid of this check: currently this class is used in jps-builders tests instead of JpsPluginManagerImpl because platform-impl module is added to classpath via testFramework + if (rootArea.hasExtensionPoint(JpsPluginBean.EP_NAME.getName())) { + rootArea.getExtensionPoint(JpsPluginBean.EP_NAME).addExtensionPointListener(new ExtensionPointListener<JpsPluginBean>() { + @Override + public void extensionAdded(@NotNull JpsPluginBean extension, @Nullable PluginDescriptor pluginDescriptor) { + ContainerUtil.addIfNotNull(pluginDescriptor, myExternalBuildPlugins); + } + + @Override + public void extensionRemoved(@NotNull JpsPluginBean extension, @Nullable PluginDescriptor pluginDescriptor) { + } + }); + } if (rootArea.hasExtensionPoint("com.intellij.compileServer.plugin")) { ExtensionPoint extensionPoint = rootArea.getExtensionPoint("com.intellij.compileServer.plugin"); + //noinspection unchecked extensionPoint.addExtensionPointListener(new ExtensionPointListener() { @Override public void extensionAdded(@NotNull Object extension, @Nullable PluginDescriptor pluginDescriptor) { - if (pluginDescriptor != null) { - myExternalBuildPlugins.add(pluginDescriptor); - } + ContainerUtil.addIfNotNull(pluginDescriptor, myExternalBuildPlugins); } @Override diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java b/platform/platform-impl/src/com/intellij/jps/impl/JpsPluginBean.java index b3d3b35b5aa2..4979dd78cfe6 100644 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteInterpreterException.java +++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsPluginBean.java @@ -13,17 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.remotesdk; +package com.intellij.jps.impl; -import com.intellij.remote.RemoteSdkException; +import com.intellij.openapi.extensions.AbstractExtensionPointBean; +import com.intellij.openapi.extensions.ExtensionPointName; /** - * @deprecated Remove in IDEA 14 - * - * @author traff + * @author nik */ -public class RemoteInterpreterException extends RemoteSdkException { - public RemoteInterpreterException(String s, Throwable throwable) { - super(s, throwable); - } +public class JpsPluginBean extends AbstractExtensionPointBean { + public static final ExtensionPointName<JpsPluginBean> EP_NAME = ExtensionPointName.create("com.intellij.jps.plugin"); } 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 308d5dbb1835..7c8acbc4c25c 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 @@ -767,12 +767,12 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App @Override public void exit() { - exit(false); + exit(false, false); } @Override - public void exit(final boolean force) { - exit(force, true, false); + public void exit(boolean force, final boolean exitConfirmed) { + exit(false, exitConfirmed, true, false); } @Override @@ -781,8 +781,8 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App } @Override - public void restart(boolean force) { - exit(force, true, true); + public void restart(boolean exitConfirmed) { + exit(false, exitConfirmed, true, true); } /* @@ -796,7 +796,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App */ private static volatile boolean exiting = false; - public void exit(final boolean force, final boolean allowListenersToCancel, final boolean restart) { + public void exit(final boolean force, final boolean exitConfirmed, final boolean allowListenersToCancel, final boolean restart) { if (exiting) return; exiting = true; @@ -808,7 +808,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App Runnable runnable = new Runnable() { @Override public void run() { - if (!confirmExitIfNeeded(force)) { + if (!force && !confirmExitIfNeeded(exitConfirmed)) { saveAll(); return; } @@ -857,9 +857,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App return true; } - private static boolean confirmExitIfNeeded(boolean force) { + private static boolean confirmExitIfNeeded(boolean exitConfirmed) { final boolean hasUnsafeBgTasks = ProgressManager.getInstance().hasUnsafeProgressIndicator(); - if (force && !hasUnsafeBgTasks) { + if (exitConfirmed && !hasUnsafeBgTasks) { return true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java index a29e51930119..3a1f8b055ab5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.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. @@ -24,8 +24,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Alarm; import com.intellij.util.containers.HashMap; -import java.util.Iterator; - public class Rediffers { private final HashMap<EditorSource, Rediff> myRediffers = new HashMap<EditorSource, Rediff>(); private final DiffPanelImpl myPanel; @@ -43,8 +41,7 @@ public class Rediffers { } public void dispose() { - for (Iterator<Rediff> iterator = myRediffers.values().iterator(); iterator.hasNext();) { - Rediff rediff = iterator.next(); + for (Rediff rediff : myRediffers.values()) { rediff.stopListen(); } myRediffers.clear(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index 8b7791086014..a0355cf71222 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -601,7 +601,9 @@ public class EditorActionUtil { } } caretModel.moveToOffset(newOffset); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + if (editor.getCaretModel().getCurrentCaret() == editor.getCaretModel().getPrimaryCaret()) { + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart); } @@ -673,7 +675,9 @@ public class EditorActionUtil { if (isWordStart(text, newOffset, camel)) break; } editor.getCaretModel().moveToOffset(newOffset); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + if (editor.getCaretModel().getCurrentCaret() == editor.getCaretModel().getPrimaryCaret()) { + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + } setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java index 48d43bcce8bd..e3c03c2fbbd4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.ex; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType; import org.jetbrains.annotations.NotNull; @@ -149,4 +150,6 @@ public interface SoftWrapModelEx extends SoftWrapModel { * Allows to instruct current model to always return <code>'true'</code> from {@link #isRespectAdditionalColumns()}. */ void forceAdditionalColumnsUsage(); + + EditorTextRepresentationHelper getEditorTextRepresentationHelper(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java index cc1a23f6f8e5..2872699c8012 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/BorderEffect.java @@ -86,6 +86,8 @@ public class BorderEffect { markupModel.processRangeHighlightersOverlappingWith(myStartOffset, myEndOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx rangeHighlighter) { + if (!rangeHighlighter.getEditorFilter().avaliableIn(myEditor)) return true; + TextAttributes textAttributes = rangeHighlighter.getTextAttributes(); if (isBorder(textAttributes) && intersectsRange(rangeHighlighter)) { paintBorder(rangeHighlighter, textAttributes); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java index 068f25e16565..cfd039a5d504 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java @@ -1453,10 +1453,17 @@ public class CaretImpl extends UserDataHolderBase implements Caret { return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset; } + @Override + @NotNull public EditorImpl getEditor() { return myEditor; } + @Override + public String toString() { + return "Caret at " + myVisibleCaret + (mySelectionMarker == null ? "" : (", selection marker: " + mySelectionMarker.toString())); + } + /** * Encapsulates information about target vertical range info - its <code>'y'</code> coordinate and height in pixels. */ diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index a18d45472454..8d6608e63dd9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -282,11 +282,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } } - boolean addCaret(CaretImpl caretToAdd) { + boolean addCaret(@NotNull CaretImpl caretToAdd) { for (CaretImpl caret : myCarets) { - VisualPosition newVisualPosition = caretToAdd.getVisualPosition(); - int newOffset = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(newVisualPosition)); - if (caret.getVisualPosition().equals(newVisualPosition) || newOffset >= caret.getSelectionStart() && newOffset <= caret.getSelectionEnd()) { + if (caretsOverlap(caret, caretToAdd)) { return false; } } @@ -384,8 +382,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, it.next(); } CaretImpl currCaret = it.next(); - if (prevCaret != null && (currCaret.getVisualPosition().equals(prevCaret.getVisualPosition()) - || selectionsIntersect(currCaret, prevCaret))) { + if (prevCaret != null && caretsOverlap(currCaret, prevCaret)) { int newSelectionStart = Math.min(currCaret.getSelectionStart(), prevCaret.getSelectionStart()); int newSelectionEnd = Math.max(currCaret.getSelectionEnd(), prevCaret.getSelectionEnd()); CaretImpl toRetain, toRemove; @@ -410,7 +407,10 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } } - private static boolean selectionsIntersect(CaretImpl firstCaret, CaretImpl secondCaret) { + private static boolean caretsOverlap(@NotNull CaretImpl firstCaret, @NotNull CaretImpl secondCaret) { + if (firstCaret.getVisualPosition().equals(secondCaret.getVisualPosition())) { + return true; + } int firstStart = firstCaret.getSelectionStart(); int secondStart = secondCaret.getSelectionStart(); int firstEnd = firstCaret.getSelectionEnd(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java index 9b2e473a0da5..61415eb90ce4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DefaultEditorTextRepresentationHelper.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,14 +16,14 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.util.EditorUtil; import gnu.trove.TObjectIntHashMap; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NotNull; /** - * Not thread-safe. + * Not thread-safe. Performs caching of char widths, so cache reset must be invoked (via {@link #clearSymbolWidthCache()} method) when + * font settings are changed in editor. * * @author Denis Zhdanov * @since Jul 27, 2010 4:06:27 PM @@ -60,9 +60,6 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen public int charWidth(char c, int fontType) { // Symbol width retrieval is detected to be a bottleneck, hence, we perform a caching here in assumption that every representation // helper is editor-bound and cache size is not too big. - EditorColorsScheme colorsScheme = myEditor.getColorsScheme(); - mySharedKey.fontName = colorsScheme.getEditorFontName(); - mySharedKey.fontSize = colorsScheme.getEditorFontSize(); mySharedKey.fontType = fontType; mySharedKey.c = c; @@ -83,9 +80,6 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen // Symbol width retrieval is detected to be a bottleneck, hence, we perform a caching here in assumption that every representation // helper is editor-bound and cache size is not too big. - EditorColorsScheme colorsScheme = myEditor.getColorsScheme(); - mySharedKey.fontName = colorsScheme.getEditorFontName(); - mySharedKey.fontSize = colorsScheme.getEditorFontSize(); mySharedKey.fontType = fontType; for (int i = startToUse; i < end; i++) { @@ -107,7 +101,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen return result; } Key key = mySharedKey.clone(); - FontInfo font = ComplementaryFontsRegistry.getFontAbleToDisplay(c, key.fontSize, key.fontType, key.fontName); + FontInfo font = ComplementaryFontsRegistry.getFontAbleToDisplay(c, key.fontType, myEditor.getColorsScheme().getFontPreferences()); result = font.charWidth(c); if (mySymbolWidthCache.size() >= MAX_SYMBOLS_WIDTHS_CACHE_SIZE) { // Don't expect to be here. @@ -117,33 +111,31 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen return result; } + public void clearSymbolWidthCache() { + mySymbolWidthCache.clear(); + } + private static class Key { - public String fontName; - private int fontSize; @JdkConstants.FontStyle private int fontType; private char c; private Key() { - this(null, 0, 0, ' '); + this(0, ' '); } - Key(String fontName, int fontSize, @JdkConstants.FontStyle int fontType, char c) { - this.fontName = fontName; - this.fontSize = fontSize; + Key(@JdkConstants.FontStyle int fontType, char c) { this.fontType = fontType; this.c = c; } @Override protected Key clone() { - return new Key(fontName, fontSize, fontType, c); + return new Key(fontType, c); } @Override public int hashCode() { - int result = fontName != null ? fontName.hashCode() : 0; - result = 31 * result + fontSize; - result = 31 * result + fontType; + int result = fontType; result = 31 * result + c; return result; } @@ -155,10 +147,8 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen Key key = (Key)o; - if (fontSize != key.fontSize) return false; if (fontType != key.fontType) return false; if (c != key.c) return false; - if (fontName != null ? !fontName.equals(key.fontName) : key.fontName != null) return false; return true; } 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 e37ad8f968ad..b708f38a9190 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 @@ -66,6 +66,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeGlassPane; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.*; @@ -320,7 +322,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myScheme = createBoundColorSchemeDelegate(null); initTabPainter(); myIsViewer = viewer; - mySettings = new SettingsImpl(this); + mySettings = new SettingsImpl(this, project); mySelectionModel = new SelectionModelImpl(this); myMarkupModel = new EditorMarkupModelImpl(this); @@ -1979,6 +1981,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myMarkupModel.processRangeHighlightersOverlappingWith(clipStartOffset, clipEndOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(@NotNull RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(EditorImpl.this)) return true; + final CustomHighlighterRenderer customRenderer = highlighter.getCustomRenderer(); if (customRenderer != null && clipStartOffset < highlighter.getEndOffset() && highlighter.getStartOffset() < clipEndOffset) { customRenderer.paint(EditorImpl.this, highlighter, g); @@ -2124,6 +2128,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi Processor<RangeHighlighterEx> paintProcessor = new Processor<RangeHighlighterEx>() { @Override public boolean process(@NotNull RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(EditorImpl.this)) return true; + paintSegmentHighlighterAfterEndOfLine(g, highlighter, startLine, endLine); return true; } @@ -2978,6 +2984,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi markupModel.processRangeHighlightersOverlappingWith(clipStartOffset, clipEndOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(@NotNull RangeHighlighterEx lineMarker) { + if (!lineMarker.getEditorFilter().avaliableIn(EditorImpl.this)) return true; + paintLineMarkerSeparator(lineMarker, clip, g); return true; } @@ -6735,7 +6743,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } } - private static class TablessBorder extends SideBorder { + private class TablessBorder extends SideBorder { private TablessBorder() { super(UIUtil.getBorderColor(), SideBorder.ALL); } @@ -6760,7 +6768,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override public Insets getBorderInsets(Component c) { Container splitters = SwingUtilities.getAncestorOfClass(EditorsSplitters.class, c); - return splitters == null ? super.getBorderInsets(c) : new Insets(1, 0, 0, 0); + boolean thereIsSomethingAbove = !SystemInfo.isMac || UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR || + EditorImpl.this.myProject != null && !ToolWindowManagerEx.getInstanceEx(EditorImpl.this.myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty(); + return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index c721a5a5873b..a2f45fe33857 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -45,6 +45,7 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.ui.*; @@ -229,6 +230,8 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark markupModel.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(myEditor)) return true; + if (highlighter.getErrorStripeMarkColor() != null) { if (highlighter.getStartOffset() < endOffset && highlighter.getEndOffset() > startOffset) { highlighters.add(highlighter); @@ -266,6 +269,8 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark markupModel.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(myEditor)) return true; + if (highlighter.getErrorStripeMarkColor() != null) { ProperTextRange range = offsetsToYPositions(highlighter.getStartOffset(), highlighter.getEndOffset()); if (scrollBarY >= range.getStartOffset() - myMinMarkHeight * 2 && @@ -432,7 +437,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark errorIconBounds.y = bounds.height / 2 - errorIconBounds.height / 2; try { - if (UISettings.getInstance().PRESENTATION_MODE) { + if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) { g.setColor(getEditor().getColorsScheme().getDefaultBackground()); g.fillRect(0, 0, bounds.width, bounds.height); @@ -523,7 +528,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark @Override protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (UISettings.getInstance().PRESENTATION_MODE) { + if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) { super.paintThumb(g, c, thumbBounds); return; } @@ -560,16 +565,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark @Override protected int getThickness() { - if (UISettings.getInstance().PRESENTATION_MODE) return super.getThickness(); + if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) return super.getThickness(); return super.getThickness() + (isMacOverlayScrollbar() ? 2 : 7); } @Override protected void doPaintTrack(Graphics g, JComponent c, Rectangle bounds) { - if (UISettings.getInstance().PRESENTATION_MODE) { + if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) { g.setColor(getEditor().getColorsScheme().getDefaultBackground()); g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); - return; + //return; } Rectangle clip = g.getClipBounds().intersection(bounds); if (clip.height == 0) return; @@ -604,7 +609,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } private void paintTrackBasement(Graphics g, Rectangle bounds) { - if (UISettings.getInstance().PRESENTATION_MODE) { + if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) { return; } @@ -661,6 +666,8 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark markup.processRangeHighlightersOverlappingWith(startOffset, endOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { + if (!highlighter.getEditorFilter().avaliableIn(myEditor)) return true; + Color color = highlighter.getErrorStripeMarkColor(); if (color == null) return true; boolean isThin = highlighter.isThinErrorStripeMark(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index 694bc75a5751..b92970425e99 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -265,9 +265,6 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList if (line >= myEditor.getDocument().getLineCount()) return null; - //leftmost folded block position - if (myEditor.xyToVisualPosition(p).equals(myEditor.logicalToVisualPosition(pos))) return null; - int offset = myEditor.logicalPositionToOffset(pos); return myFoldTree.fetchOutermost(offset); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java index 263ea77c286f..2f5a81153579 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 @@ -36,16 +36,13 @@ 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.ide.CopyPasteManager; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.awt.datatransfer.StringSelection; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; @@ -570,13 +567,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi @Override public void copySelectionToClipboard() { - validateContext(true); - String s = getSelectedText(true); - if (s == null) return; - - s = StringUtil.convertLineSeparators(s); - StringSelection contents = new StringSelection(s); - CopyPasteManager.getInstance().setContents(contents); + CopyPasteSupport.copySelectionToClipboard(myEditor); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java index dabf5e9d2a2f..f2dbc6756ef5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java @@ -25,6 +25,8 @@ package com.intellij.openapi.editor.impl; import com.intellij.codeStyle.CodeStyleFacade; +import com.intellij.lang.Language; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorSettings; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; @@ -32,10 +34,14 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SettingsImpl implements EditorSettings { @Nullable private final EditorEx myEditor; + @Nullable private final Language myLanguage; private Boolean myIsCamelWords; // This group of settings does not have UI @@ -78,9 +84,14 @@ public class SettingsImpl implements EditorSettings { private Boolean myRenamePreselect = null; private Boolean myWrapWhenTypingReachesRightMargin = null; private Boolean myShowIntentionBulb = null; + + public SettingsImpl() { + this(null, null); + } - public SettingsImpl(@Nullable EditorEx editor) { + public SettingsImpl(@Nullable EditorEx editor, @Nullable Project project) { myEditor = editor; + myLanguage = editor != null && project != null ? getDocumentLanguage(project, editor.getDocument()) : null; } @Override @@ -144,7 +155,17 @@ public class SettingsImpl implements EditorSettings { @Override public int getRightMargin(Project project) { return myRightMargin != null ? myRightMargin.intValue() : - CodeStyleFacade.getInstance(project).getRightMargin(); + CodeStyleFacade.getInstance(project).getRightMargin(myLanguage); + } + + @Nullable + private static Language getDocumentLanguage(@Nullable Project project, @NotNull Document document) { + if (project != null) { + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); + PsiFile file = documentManager.getPsiFile(document); + if (file != null) return file.getLanguage(); + } + return null; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index cccf86c5f98e..6f1b9820132b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.colors.FontPreferences; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.ex.*; @@ -89,9 +90,10 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private SoftWrapPainter myPainter; private final SoftWrapApplianceManager myApplianceManager; private final SoftWrapAwareVisualSizeManager myVisualSizeManager; + private EditorTextRepresentationHelper myEditorTextRepresentationHelper; private final EditorEx myEditor; - + /** * We don't want to use soft wraps-aware processing from non-EDT and profiling shows that 'is EDT' check that is called too * often is rather expensive. Hence, we use caching here for performance improvement. @@ -101,6 +103,8 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private int myActive; private boolean myUseSoftWraps; private int myTabWidth = -1; + @NotNull + private FontPreferences myFontPreferences; /** * Soft wraps need to be kept up-to-date on all editor modification (changing text, adding/removing/expanding/collapsing fold @@ -132,9 +136,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myEditor = editor; myStorage = new SoftWrapsStorage(); myPainter = new CompositeSoftWrapPainter(editor); - DefaultEditorTextRepresentationHelper representationHelper = new DefaultEditorTextRepresentationHelper(editor); - myDataMapper = new CachingSoftWrapDataMapper(editor, myStorage, representationHelper); - myApplianceManager = new SoftWrapApplianceManager(myStorage, editor, myPainter, representationHelper, myDataMapper); + myEditorTextRepresentationHelper = new DefaultEditorTextRepresentationHelper(editor); + myDataMapper = new CachingSoftWrapDataMapper(editor, myStorage); + myApplianceManager = new SoftWrapApplianceManager(myStorage, editor, myPainter, myDataMapper); myFoldBasedApplianceStrategy = new SoftWrapFoldBasedApplianceStrategy(editor); myVisualSizeManager = new SoftWrapAwareVisualSizeManager(myPainter); @@ -150,6 +154,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi }); EditorSettings settings = myEditor.getSettings(); myUseSoftWraps = settings.isUseSoftWraps(); + myFontPreferences = myEditor.getColorsScheme().getFontPreferences(); editor.addPropertyChangeListener(this); @@ -168,8 +173,16 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi int tabWidthBefore = myTabWidth; myTabWidth = getCurrentTabWidth(); + + boolean fontsChanged = false; + if (!myFontPreferences.equals(myEditor.getColorsScheme().getFontPreferences()) + && myEditorTextRepresentationHelper instanceof DefaultEditorTextRepresentationHelper) { + fontsChanged = true; + myFontPreferences = myEditor.getColorsScheme().getFontPreferences(); + ((DefaultEditorTextRepresentationHelper)myEditorTextRepresentationHelper).clearSymbolWidthCache(); + } - if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore)) { + if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore) || fontsChanged) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); @@ -705,6 +718,20 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myVisualSizeManager.setSoftWrapPainter(painter); } + public static EditorTextRepresentationHelper getEditorTextRepresentationHelper(@NotNull Editor editor) { + return ((SoftWrapModelEx)editor.getSoftWrapModel()).getEditorTextRepresentationHelper(); + } + + public EditorTextRepresentationHelper getEditorTextRepresentationHelper() { + return myEditorTextRepresentationHelper; + } + + @TestOnly + public void setEditorTextRepresentationHelper(EditorTextRepresentationHelper editorTextRepresentationHelper) { + myEditorTextRepresentationHelper = editorTextRepresentationHelper; + myApplianceManager.reset(); + } + @NotNull @Override public String dumpState() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java index 26c8086beb72..bccdf4c59336 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java @@ -15,12 +15,10 @@ */ package com.intellij.openapi.editor.impl.softwrap.mapping; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,10 +37,7 @@ import java.util.List; */ abstract class AbstractMappingStrategy<T> implements MappingStrategy<T> { - private static final Logger LOG = Logger.getInstance("#" + AbstractMappingStrategy.class.getName()); - protected final Editor myEditor; - protected final EditorTextRepresentationHelper myRepresentationHelper; protected final SoftWrapsStorage myStorage; protected final List<CacheEntry> myCache; @@ -53,13 +48,11 @@ abstract class AbstractMappingStrategy<T> implements MappingStrategy<T> { AbstractMappingStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, - @NotNull List<CacheEntry> cache, - @NotNull EditorTextRepresentationHelper representationHelper) + @NotNull List<CacheEntry> cache) { myEditor = editor; myStorage = storage; myCache = cache; - myRepresentationHelper = representationHelper; } @Nullable @@ -73,7 +66,7 @@ abstract class AbstractMappingStrategy<T> implements MappingStrategy<T> { } protected void setFirstInitialPosition() { - myInitialPosition = new EditorPosition(new LogicalPosition(0, 0), 0, myEditor, myRepresentationHelper); + myInitialPosition = new EditorPosition(new LogicalPosition(0, 0), 0, myEditor); } @Nullable diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CacheEntry.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CacheEntry.java index 57ef56c178e9..27362b52527a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CacheEntry.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CacheEntry.java @@ -17,7 +17,6 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.util.Ref; import gnu.trove.TIntObjectHashMap; import gnu.trove.TIntObjectProcedure; @@ -25,7 +24,10 @@ import gnu.trove.TObjectProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * Encapsulates information to cache for the single visual line. @@ -59,7 +61,6 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable { public boolean locked; private final Editor myEditor; - private final EditorTextRepresentationHelper myRepresentationHelper; /** Holds positions for the tabulation symbols on a target visual line sorted by offset in ascending order. */ private List<TabData> myTabPositions = Collections.EMPTY_LIST; @@ -67,10 +68,9 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable { /** Holds information about single line fold regions representation data. */ private TIntObjectHashMap<FoldingData> myFoldingData = DUMMY; - CacheEntry(int visualLine, @NotNull Editor editor, @NotNull EditorTextRepresentationHelper representationHelper) { + CacheEntry(int visualLine, @NotNull Editor editor) { this.visualLine = visualLine; myEditor = editor; - myRepresentationHelper = representationHelper; } public void setLineStartPosition(@NotNull EditorPosition context) { @@ -99,7 +99,7 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable { } public EditorPosition buildStartLinePosition() { - EditorPosition result = new EditorPosition(myEditor, myRepresentationHelper); + EditorPosition result = new EditorPosition(myEditor); result.logicalLine = startLogicalLine; result.logicalColumn = startLogicalColumn; result.offset = startOffset; @@ -114,7 +114,7 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable { } public EditorPosition buildEndLinePosition() { - EditorPosition result = new EditorPosition(myEditor, myRepresentationHelper); + EditorPosition result = new EditorPosition(myEditor); result.logicalLine = endLogicalLine; result.logicalColumn = endLogicalColumn; result.offset = endOffset; @@ -246,7 +246,7 @@ class CacheEntry implements Comparable<CacheEntry>, Cloneable { @Override protected CacheEntry clone() { - final CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper); + final CacheEntry result = new CacheEntry(visualLine, myEditor); result.startLogicalLine = startLogicalLine; result.startLogicalColumn = startLogicalColumn; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java index 08bf0211dbc8..2f21b0319af2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java @@ -21,7 +21,7 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.editor.impl.EditorImpl; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.impl.softwrap.SoftWrapDataMapper; import com.intellij.openapi.editor.impl.softwrap.SoftWrapImpl; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; @@ -71,19 +71,16 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw private final VisualToLogicalCalculationStrategy myVisualToLogicalStrategy; private final EditorEx myEditor; private final SoftWrapsStorage myStorage; - private final EditorTextRepresentationHelper myRepresentationHelper; private final CacheEntry mySearchKey; - public CachingSoftWrapDataMapper(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage, - @NotNull EditorTextRepresentationHelper representationHelper) + public CachingSoftWrapDataMapper(@NotNull EditorEx editor, @NotNull SoftWrapsStorage storage) { myEditor = editor; myStorage = storage; - myRepresentationHelper = representationHelper; - mySearchKey = new CacheEntry(0, editor, representationHelper); + mySearchKey = new CacheEntry(0, editor); - myOffsetToLogicalStrategy = new OffsetToLogicalCalculationStrategy(editor, storage, myCache, representationHelper); - myVisualToLogicalStrategy = new VisualToLogicalCalculationStrategy(editor, storage, myCache, representationHelper); + myOffsetToLogicalStrategy = new OffsetToLogicalCalculationStrategy(editor, storage, myCache); + myVisualToLogicalStrategy = new VisualToLogicalCalculationStrategy(editor, storage, myCache); } @NotNull @@ -146,7 +143,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw // Count soft wrap column offset only if it's located at the same line as the target offset. if (column < 0 && softWrap.getStart() >= targetLogicalLineStartOffset) { - column = softWrap.getIndentInColumns() + myRepresentationHelper.toVisualColumnSymbolsNumber( + column = softWrap.getIndentInColumns() + SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor).toVisualColumnSymbolsNumber( myEditor.getDocument().getCharsSequence(), softWrap.getStart(), maxOffset, softWrap.getIndentInPixels() ); @@ -326,7 +323,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw return lastEntry; } else if (lastEntry.visualLine < visualLine && createIfNecessary) { - CacheEntry result = new CacheEntry(visualLine, myEditor, myRepresentationHelper); + CacheEntry result = new CacheEntry(visualLine, myEditor); myCache.add(result); return result; } @@ -357,7 +354,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw if (cacheEntryIndex < 0) { cacheEntryIndex = start; if (createIfNecessary) { - myCache.add(cacheEntryIndex, result = new CacheEntry(visualLine, myEditor, myRepresentationHelper)); + myCache.add(cacheEntryIndex, result = new CacheEntry(visualLine, myEditor)); } } else { @@ -666,7 +663,7 @@ public class CachingSoftWrapDataMapper implements SoftWrapDataMapper, SoftWrapAw @NotNull List<Pair<Integer, FoldRegion>> foldRegions, @NotNull List<Pair<Integer, Integer>> tabData) { - final CacheEntry entry = new CacheEntry(visualLine, myEditor, myRepresentationHelper); + final CacheEntry entry = new CacheEntry(visualLine, myEditor); entry.startOffset = startOffset; entry.endOffset = endOffset; entry.startLogicalLine = startLogicalLine; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/EditorPosition.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/EditorPosition.java index 903243cfa766..1097f2824445 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/EditorPosition.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/EditorPosition.java @@ -16,7 +16,7 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import org.jetbrains.annotations.NotNull; /** @@ -46,29 +46,24 @@ class EditorPosition implements Cloneable { public int symbolWidthInPixels; private final Editor myEditor; - private final EditorTextRepresentationHelper myRepresentationHelper; - EditorPosition(@NotNull Editor editor, @NotNull EditorTextRepresentationHelper representationHelper) { + EditorPosition(@NotNull Editor editor) { myEditor = editor; - myRepresentationHelper = representationHelper; } EditorPosition(@NotNull LogicalPosition logical, int offset, - @NotNull Editor editor, - @NotNull EditorTextRepresentationHelper representationHelper) + @NotNull Editor editor) { - this(logical, logical.toVisualPosition(), offset, editor, representationHelper); + this(logical, logical.toVisualPosition(), offset, editor); } EditorPosition(@NotNull LogicalPosition logical, @NotNull VisualPosition visual, int offset, - @NotNull Editor editor, - @NotNull EditorTextRepresentationHelper representationHelper) + @NotNull Editor editor) { myEditor = editor; - myRepresentationHelper = representationHelper; logicalLine = logical.line; logicalColumn = logical.column; softWrapLinesBefore = logical.softWrapLinesBeforeCurrentLogicalLine; @@ -148,10 +143,11 @@ class EditorPosition implements Cloneable { if (logicalLine == endOffsetLogicalLine) { // Single-line fold region. if (collapsedSymbolsWidthInColumns < 0) { - collapsedSymbolsWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(document.getCharsSequence(), - foldRegion.getStartOffset(), - foldRegion.getEndOffset(), - x); + collapsedSymbolsWidthInColumns = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor) + .toVisualColumnSymbolsNumber(document.getCharsSequence(), + foldRegion.getStartOffset(), + foldRegion.getEndOffset(), + x); } logicalColumn += collapsedSymbolsWidthInColumns; foldingColumnDiff += placeholder.length() - collapsedSymbolsWidthInColumns; @@ -159,10 +155,11 @@ class EditorPosition implements Cloneable { else { // Multi-line fold region. if (collapsedSymbolsWidthInColumns < 0) { - collapsedSymbolsWidthInColumns = myRepresentationHelper.toVisualColumnSymbolsNumber(document.getCharsSequence(), - foldRegion.getStartOffset(), - foldRegion.getEndOffset(), - 0); + collapsedSymbolsWidthInColumns = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor) + .toVisualColumnSymbolsNumber(document.getCharsSequence(), + foldRegion.getStartOffset(), + foldRegion.getEndOffset(), + 0); } int linesDiff = endOffsetLogicalLine - logicalLine; logicalLine += linesDiff; @@ -191,7 +188,7 @@ class EditorPosition implements Cloneable { @Override protected EditorPosition clone() { - EditorPosition result = new EditorPosition(myEditor, myRepresentationHelper); + EditorPosition result = new EditorPosition(myEditor); result.logicalLine = logicalLine; result.logicalColumn = logicalColumn; result.visualLine = visualLine; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java index 773d4fdc4d82..6ed904624fa6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java @@ -16,7 +16,7 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; import org.jetbrains.annotations.NotNull; @@ -32,10 +32,10 @@ class LogicalToVisualMappingStrategy extends AbstractMappingStrategy<VisualPosit private LogicalPosition myTargetLogical; LogicalToVisualMappingStrategy(@NotNull LogicalPosition logical, @NotNull Editor editor, @NotNull SoftWrapsStorage storage, - @NotNull EditorTextRepresentationHelper representationHelper, @NotNull List<CacheEntry> cache) + @NotNull List<CacheEntry> cache) throws IllegalStateException { - super(editor, storage, cache, representationHelper); + super(editor, storage, cache); myTargetLogical = logical; } @@ -121,7 +121,7 @@ class LogicalToVisualMappingStrategy extends AbstractMappingStrategy<VisualPosit int foldEndColumn; if (data == null) { int xStart = myEditor.getDocument().getLineNumber(foldRegion.getStartOffset()) == foldEndLine ? context.x : 0; - foldEndColumn = myRepresentationHelper.toVisualColumnSymbolsNumber( + foldEndColumn = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor).toVisualColumnSymbolsNumber( myEditor.getDocument().getCharsSequence(), foldRegion.getStartOffset(), foldRegion.getEndOffset(), xStart ); } else { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java index 39fe252ec623..399406f2db32 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java @@ -16,7 +16,7 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,10 +31,9 @@ class OffsetToLogicalCalculationStrategy extends AbstractMappingStrategy<Logical private int myTargetOffset; - OffsetToLogicalCalculationStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, @NotNull List<CacheEntry> cache, - @NotNull EditorTextRepresentationHelper representationHelper) + OffsetToLogicalCalculationStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, @NotNull List<CacheEntry> cache) { - super(editor, storage, cache, representationHelper); + super(editor, storage, cache); } public void init(final int targetOffset, final List<CacheEntry> cache) { @@ -157,13 +156,13 @@ class OffsetToLogicalCalculationStrategy extends AbstractMappingStrategy<Logical int targetLogicalLine = document.getLineNumber(myTargetOffset); if (targetLogicalLine == position.logicalLine) { // Target offset is located on the same logical line as folding start. - position.logicalColumn += myRepresentationHelper.toVisualColumnSymbolsNumber( + position.logicalColumn += SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor).toVisualColumnSymbolsNumber( document.getCharsSequence(), foldRegion.getStartOffset(), myTargetOffset, position.x ); } else { // Target offset is located on a different line with folding start. - position.logicalColumn = myRepresentationHelper.toVisualColumnSymbolsNumber( + position.logicalColumn = SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor).toVisualColumnSymbolsNumber( document.getCharsSequence(), foldRegion.getStartOffset(), myTargetOffset, 0 ); position.softWrapColumnDiff = 0; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 549cd1833779..3a819d88a370 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -28,10 +28,7 @@ import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.ScrollingModelEx; import com.intellij.openapi.editor.ex.util.EditorUtil; -import com.intellij.openapi.editor.impl.EditorImpl; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; -import com.intellij.openapi.editor.impl.IterationState; -import com.intellij.openapi.editor.impl.TextChangeImpl; +import com.intellij.openapi.editor.impl.*; import com.intellij.openapi.editor.impl.softwrap.*; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.text.StringUtil; @@ -99,7 +96,6 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { private int myVerticalScrollBarWidth = -1; private VisibleAreaWidthProvider myWidthProvider; - private EditorTextRepresentationHelper myRepresentationHelper; private LineWrapPositionStrategy myLineWrapPositionStrategy; private IncrementalCacheUpdateEvent myEventBeingProcessed; private boolean myVisualAreaListenerAttached; @@ -112,12 +108,11 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { public SoftWrapApplianceManager(@NotNull SoftWrapsStorage storage, @NotNull EditorEx editor, @NotNull SoftWrapPainter painter, - @NotNull EditorTextRepresentationHelper representationHelper, SoftWrapDataMapper dataMapper) + SoftWrapDataMapper dataMapper) { myStorage = storage; myEditor = editor; myPainter = painter; - myRepresentationHelper = representationHelper; myDataMapper = dataMapper; myWidthProvider = new DefaultVisibleAreaWidthProvider(editor); } @@ -272,7 +267,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { myContext.fontType = attributes.getFontType(); myContext.rangeEndOffset = event.getNewEndOffset(); - EditorPosition position = new EditorPosition(logical, start, myEditor, myRepresentationHelper); + EditorPosition position = new EditorPosition(logical, start, myEditor); position.x = point.x; int spaceWidth = EditorUtil.getSpaceWidth(myContext.fontType, myEditor); @@ -333,7 +328,8 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { } int placeholderWidthInPixels = 0; for (int i = 0; i < placeholder.length(); i++) { - placeholderWidthInPixels += myRepresentationHelper.charWidth(placeholder.charAt(i), myContext.fontType); + placeholderWidthInPixels += SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor) + .charWidth(placeholder.charAt(i), myContext.fontType); } int newX = myContext.currentPosition.x + placeholderWidthInPixels; @@ -617,7 +613,7 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { return EditorUtil.nextTabStop(myContext.currentPosition.x, myEditor); } else { - return myContext.currentPosition.x + myRepresentationHelper.charWidth(c, myContext.fontType); + return myContext.currentPosition.x + SoftWrapModelImpl.getEditorTextRepresentationHelper(myEditor).charWidth(c, myContext.fontType); //FontInfo fontInfo = EditorUtil.fontForChar(c, myContext.fontType, myEditor); //return myContext.currentPosition.x + fontInfo.charWidth(c, myContext.contentComponent); } @@ -1009,11 +1005,6 @@ public class SoftWrapApplianceManager implements DocumentListener, Dumpable { reset(); } - public void setRepresentationHelper(@NotNull EditorTextRepresentationHelper representationHelper) { - myRepresentationHelper = representationHelper; - reset(); - } - @NotNull @Override public String dumpState() { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/VisualToLogicalCalculationStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/VisualToLogicalCalculationStrategy.java index d79e3bff8f63..7c7c6e475a4f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/VisualToLogicalCalculationStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/VisualToLogicalCalculationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,11 +32,10 @@ class VisualToLogicalCalculationStrategy extends AbstractMappingStrategy<Logical private final CacheEntry mySearchKey; private VisualPosition myTargetVisual; - VisualToLogicalCalculationStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, @NotNull List<CacheEntry> cache, - @NotNull EditorTextRepresentationHelper representationHelper) + VisualToLogicalCalculationStrategy(@NotNull Editor editor, @NotNull SoftWrapsStorage storage, @NotNull List<CacheEntry> cache) { - super(editor, storage, cache, representationHelper); - mySearchKey = new CacheEntry(0, editor, representationHelper); + super(editor, storage, cache); + mySearchKey = new CacheEntry(0, editor); } public void init(@NotNull final VisualPosition targetVisual, @NotNull final List<CacheEntry> cache) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java index 5541e61f54fb..92ef12c46558 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java @@ -29,6 +29,12 @@ public class TextComponentCaret extends UserDataHolderBase implements Caret { @NotNull @Override + public Editor getEditor() { + return myEditor; + } + + @NotNull + @Override public CaretModel getCaretModel() { return myEditor.getCaretModel(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java index 80e0cbbc128b..486a7c511016 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java @@ -136,7 +136,7 @@ public class TextComponentEditor extends UserDataHolderBase implements Editor { @NotNull public EditorSettings getSettings() { if (mySettings == null) { - mySettings = new SettingsImpl(null); + mySettings = new SettingsImpl(); } return mySettings; } 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 860ba3211c4b..3519ab6a1af4 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 @@ -264,11 +264,11 @@ public class EditorWindow { } public void closeFile(final VirtualFile file) { - closeFile (file, true); + closeFile(file, true); } - public void closeFile(final VirtualFile file, final boolean unsplit) { - closeFile(file, unsplit, true); + public void closeFile(final VirtualFile file, final boolean disposeIfNeeded) { + closeFile(file, disposeIfNeeded, true); } public boolean hasClosedTabs() { @@ -286,7 +286,7 @@ public class EditorWindow { } } - public void closeFile(final VirtualFile file, final boolean unsplit, final boolean transferFocus) { + public void closeFile(final VirtualFile file, final boolean disposeIfNeeded, final boolean transferFocus) { final FileEditorManagerImpl editorManager = getManager(); editorManager.runChange(new FileEditorManagerChange() { @Override @@ -317,13 +317,15 @@ public class EditorWindow { } } - if (unsplit && getTabCount() == 0) { - unsplit (true); + if (disposeIfNeeded && getTabCount() == 0) { + removeFromSplitter(); } - myPanel.revalidate (); - if (myTabbedPane == null) { - // in tabless mode - myPanel.repaint(); + else { + myPanel.revalidate(); + if (myTabbedPane == null) { + // in tabless mode + myPanel.repaint(); + } } } finally { @@ -347,6 +349,39 @@ public class EditorWindow { }, myOwner); } + private void removeFromSplitter() { + if (!inSplitter()) return; + + if (myOwner.getCurrentWindow() == this) { + EditorWindow[] siblings = findSiblings(); + myOwner.setCurrentWindow(siblings[0], false); + } + + Splitter splitter = (Splitter)myPanel.getParent(); + JComponent otherComponent = splitter.getOtherComponent(myPanel); + + Container parent = splitter.getParent().getParent(); + if (parent instanceof Splitter) { + Splitter parentSplitter = (Splitter)parent; + if (parentSplitter.getFirstComponent() == splitter.getParent()) { + parentSplitter.setFirstComponent(otherComponent); + } + else { + parentSplitter.setSecondComponent(otherComponent); + } + } + else if (parent instanceof EditorsSplitters) { + parent.removeAll(); + parent.add(otherComponent, BorderLayout.CENTER); + ((JComponent)parent).revalidate(); + } + else { + throw new IllegalStateException("Unknown container: " + parent); + } + + dispose(); + } + private int calcIndexToSelect(VirtualFile fileBeingClosed, final int fileIndex) { final int currentlySelectedIndex = myTabbedPane.getSelectedIndex(); if (currentlySelectedIndex != fileIndex) { @@ -503,6 +538,8 @@ public class EditorWindow { public void requestFocus(boolean forced) { if (myTabbedPane != null) { myTabbedPane.requestFocus(forced); + } else { + IdeFocusManager.findInstanceByComponent(myPanel).requestFocus(myPanel, forced); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index 5def1e1fc161..f396b1eed399 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -173,8 +173,12 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt document.setModificationStamp(file.getModificationStamp()); final FileType fileType = file.getFileType(); document.setReadOnly(!file.isWritable() || fileType.isBinary()); - myDocuments.put(file, document); - document.putUserData(FILE_KEY, file); + if (file instanceof LightVirtualFile) { + registerDocument(document, file); + } else { + myDocuments.put(file, document); + document.putUserData(FILE_KEY, file); + } if (!(file instanceof LightVirtualFile || file.getFileSystem() instanceof DummyFileSystem)) { document.addDocumentListener( 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 34be36b69435..9a566e9915ef 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 @@ -314,6 +314,30 @@ public final class IdeKeyEventDispatcher implements Disposable { } } + private static KeyStroke getKeyStrokeWithoutCtrlModifier(KeyStroke originalKeyStroke){ + int modifier=originalKeyStroke.getModifiers()&~InputEvent.CTRL_MASK&~InputEvent.CTRL_DOWN_MASK; + try { + Method[] methods=AWTKeyStroke.class.getDeclaredMethods(); + Method getCachedStrokeMethod=null; + for (Method method : methods) { + if (GET_CACHED_STROKE_METHOD_NAME.equals(method.getName())) { + getCachedStrokeMethod = method; + getCachedStrokeMethod.setAccessible(true); + break; + } + } + if(getCachedStrokeMethod==null){ + throw new IllegalStateException("not found method with name getCachedStrokeMethod"); + } + Object[] getCachedStrokeMethodArgs= + {originalKeyStroke.getKeyChar(), originalKeyStroke.getKeyCode(), modifier, originalKeyStroke.isOnKeyRelease()}; + return (KeyStroke)getCachedStrokeMethod.invoke(originalKeyStroke, getCachedStrokeMethodArgs); + } + catch(Exception exc){ + throw new IllegalStateException(exc.getMessage()); + } + } + private boolean inSecondStrokeInProgressState() { KeyEvent e = myContext.getInputEvent(); @@ -396,6 +420,15 @@ public final class IdeKeyEventDispatcher implements Disposable { KeyStroke originalKeyStroke=KeyStroke.getKeyStrokeForEvent(e); KeyStroke keyStroke=getKeyStrokeWithoutMouseModifiers(originalKeyStroke); + + + if (Registry.is("fix.jdk7.alt.shortcuts") && SystemInfo.isMac && SystemInfo.isOracleJvm && (keyStroke.getModifiers() & InputEvent.ALT_MASK) == InputEvent.ALT_MASK) + { + if (KeymapManager.getInstance().getActiveKeymap().getActionIds(new KeyboardShortcut(keyStroke, null)).length == 0) { + keyStroke = getKeyStrokeWithoutCtrlModifier(keyStroke); + } + } + if (myKeyGestureProcessor.processInitState()) { return true; } @@ -601,7 +634,9 @@ public final class IdeKeyEventDispatcher implements Disposable { processor.onUpdatePassed(e, action, actionEvent); - ((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount(), this); + if (myContext.getDataContext() instanceof DataManagerImpl.MyDataContext) { // this is not true for test data contexts + ((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount(), this); + } actionManager.fireBeforeActionPerformed(action, actionEvent.getDataContext(), actionEvent); Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(actionEvent.getDataContext()); if (component != null && !component.isShowing()) { 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 4c093211cfd6..7b4f5a0371ba 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 @@ -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. @@ -15,6 +15,7 @@ */ package com.intellij.openapi.keymap.impl; +import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; @@ -27,6 +28,7 @@ import com.intellij.openapi.options.SchemesManager; import com.intellij.openapi.options.SchemesManagerFactory; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.registry.Registry; import com.intellij.util.containers.ContainerUtil; import org.jdom.Document; import org.jdom.Element; @@ -35,6 +37,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.event.KeyEvent; import java.io.File; import java.io.IOException; import java.util.*; @@ -92,6 +95,14 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat } } load(); + + if (Registry.is("editor.add.carets.on.double.control.arrows")) { + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, KeyEvent.VK_CONTROL, KeyEvent.VK_UP); + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, KeyEvent.VK_CONTROL, KeyEvent.VK_DOWN); + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT); + ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT); + } + ourKeymapManagerInitialized = true; } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java new file mode 100644 index 000000000000..28536453b713 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java @@ -0,0 +1,210 @@ +/* + * 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.keymap.impl; + +import com.intellij.ide.DataManager; +import com.intellij.ide.IdeEventQueue; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.util.Clock; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.util.containers.ConcurrentHashMap; +import gnu.trove.TIntIntHashMap; +import gnu.trove.TIntIntProcedure; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Support for keyboard shortcuts like Control-double-click or Control-double-click+A + */ +public class ModifierKeyDoubleClickHandler { + private static final ModifierKeyDoubleClickHandler INSTANCE = new ModifierKeyDoubleClickHandler(); + + private final ConcurrentMap<String, IdeEventQueue.EventDispatcher> myDispatchers = new ConcurrentHashMap<String, IdeEventQueue.EventDispatcher>(); + + private ModifierKeyDoubleClickHandler() { } + + public static ModifierKeyDoubleClickHandler getInstance() { + return INSTANCE; + } + + /** + * @param actionId Id of action to be triggered on modifier+modifier[+actionKey] + * @param modifierKeyCode keyCode for modifier, e.g. KeyEvent.VK_SHIFT + * @param actionKeyCode keyCode for actionKey, or -1 if action should be triggered on bare modifier double click + */ + public void registerAction(@NotNull String actionId, + int modifierKeyCode, + int actionKeyCode) { + final MyDispatcher dispatcher = new MyDispatcher(actionId, modifierKeyCode, actionKeyCode); + IdeEventQueue.EventDispatcher oldDispatcher = myDispatchers.put(actionId, dispatcher); + IdeEventQueue.getInstance().addDispatcher(dispatcher, null); + if (oldDispatcher != null) { + IdeEventQueue.getInstance().removeDispatcher(oldDispatcher); + } + } + + public void unregisterAction(@NotNull String actionId) { + IdeEventQueue.EventDispatcher oldDispatcher = myDispatchers.remove(actionId); + if (oldDispatcher != null) { + IdeEventQueue.getInstance().removeDispatcher(oldDispatcher); + } + } + + private static class MyDispatcher implements IdeEventQueue.EventDispatcher { + private static final TIntIntHashMap KEY_CODE_TO_MODIFIER_MAP = new TIntIntHashMap(); + static { + KEY_CODE_TO_MODIFIER_MAP.put(KeyEvent.VK_ALT, InputEvent.ALT_MASK); + KEY_CODE_TO_MODIFIER_MAP.put(KeyEvent.VK_CONTROL, InputEvent.CTRL_MASK); + KEY_CODE_TO_MODIFIER_MAP.put(KeyEvent.VK_META, InputEvent.META_MASK); + KEY_CODE_TO_MODIFIER_MAP.put(KeyEvent.VK_SHIFT, InputEvent.SHIFT_MASK); + } + + private final String myActionId; + private final int myModifierKeyCode; + private final int myActionKeyCode; + + private final Couple<AtomicBoolean> ourPressed = Couple.of(new AtomicBoolean(false), new AtomicBoolean(false)); + private final Couple<AtomicBoolean> ourReleased = Couple.of(new AtomicBoolean(false), new AtomicBoolean(false)); + private final AtomicBoolean ourOtherKeyWasPressed = new AtomicBoolean(false); + private final AtomicLong ourLastTimePressed = new AtomicLong(0); + + public MyDispatcher(@NotNull String actionId, int modifierKeyCode, int actionKeyCode) { + myActionId = actionId; + myModifierKeyCode = modifierKeyCode; + myActionKeyCode = actionKeyCode; + } + + @Override + public boolean dispatch(AWTEvent event) { + if (event instanceof KeyEvent) { + final KeyEvent keyEvent = (KeyEvent)event; + final int keyCode = keyEvent.getKeyCode(); + + if (keyCode == myModifierKeyCode) { + if (hasOtherModifiers(keyEvent)) { + resetState(); + return false; + } + if (ourOtherKeyWasPressed.get() && Clock.getTime() - ourLastTimePressed.get() < 500) { + resetState(); + return false; + } + ourOtherKeyWasPressed.set(false); + if (ourPressed.first.get() && Clock.getTime() - ourLastTimePressed.get() > 500) { + resetState(); + } + handleModifier((KeyEvent)event); + return false; + } else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get() && myActionKeyCode != -1) { + if (keyCode == myActionKeyCode) { + if (event.getID() == KeyEvent.KEY_RELEASED) { + run(keyEvent); + } + return true; + } + return false; + } else { + ourLastTimePressed.set(Clock.getTime()); + ourOtherKeyWasPressed.set(true); + if (keyCode == KeyEvent.VK_ESCAPE || keyCode == KeyEvent.VK_TAB) { + ourLastTimePressed.set(0); + } + } + resetState(); + } + return false; + } + + private boolean hasOtherModifiers(KeyEvent keyEvent) { + final int modifiers = keyEvent.getModifiers(); + return !KEY_CODE_TO_MODIFIER_MAP.forEachEntry(new TIntIntProcedure() { + @Override + public boolean execute(int keyCode, int modifierMask) { + return keyCode == myModifierKeyCode || (modifiers & modifierMask) == 0; + } + }); + } + + private void handleModifier(KeyEvent event) { + if (ourPressed.first.get() && Clock.getTime() - ourLastTimePressed.get() > 300) { + resetState(); + return; + } + + if (event.getID() == KeyEvent.KEY_PRESSED) { + if (!ourPressed.first.get()) { + resetState(); + ourPressed.first.set(true); + ourLastTimePressed.set(Clock.getTime()); + return; + } else { + if (ourPressed.first.get() && ourReleased.first.get()) { + ourPressed.second.set(true); + ourLastTimePressed.set(Clock.getTime()); + return; + } + } + } else if (event.getID() == KeyEvent.KEY_RELEASED) { + if (ourPressed.first.get() && !ourReleased.first.get()) { + ourReleased.first.set(true); + ourLastTimePressed.set(Clock.getTime()); + return; + } else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get()) { + resetState(); + if (myActionKeyCode == -1 && !isActionBound()) { + run(event); + } + return; + } + } + resetState(); + } + + private void resetState() { + ourPressed.first.set(false); + ourPressed.second.set(false); + ourReleased.first.set(false); + ourReleased.second.set(false); + } + + private void run(KeyEvent event) { + final ActionManager actionManager = ActionManager.getInstance(); + final AnAction action = actionManager.getAction(myActionId); + final AnActionEvent anActionEvent = new AnActionEvent(event, + DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()), + ActionPlaces.MAIN_MENU, + action.getTemplatePresentation(), + actionManager, + 0); + action.actionPerformed(anActionEvent); + } + + private boolean isActionBound() { + return KeymapManager.getInstance().getActiveKeymap().getShortcuts(myActionId).length > 0; + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java new file mode 100644 index 000000000000..104dc7b30ec7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java @@ -0,0 +1,52 @@ +package com.intellij.openapi.options; + +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implements SearchableConfigurable, Configurable.NoScroll { + private UI ui; + + @Nullable + @Override + public Runnable enableSearch(String option) { + return null; + } + + protected abstract S getSettings(); + + @Override + public void reset() { + if (ui != null) { + ui.reset(getSettings()); + } + } + + @Nullable + @Override + public final JComponent createComponent() { + if (ui == null) { + ui = createUi(); + } + return ui.getComponent(); + } + + protected abstract UI createUi(); + + @Override + public final boolean isModified() { + return ui != null && ui.isModified(getSettings()); + } + + @Override + public final void apply() { + if (ui != null) { + ui.apply(getSettings()); + } + } + + @Override + public void disposeUIResources() { + ui = null; + } +}
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java new file mode 100644 index 000000000000..e454099318ea --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java @@ -0,0 +1,16 @@ +package com.intellij.openapi.options; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public interface ConfigurableUi<S> { + void reset(@NotNull S settings); + + boolean isModified(@NotNull S settings); + + void apply(@NotNull S settings); + + @NotNull + JComponent getComponent(); +}
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java index ed72e27e8c22..5f8dc0e890df 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,8 +47,17 @@ public class ConfigurableWrapper implements SearchableConfigurable { @Nullable public static <T extends UnnamedConfigurable> T wrapConfigurable(ConfigurableEP<T> ep) { - if (ep.displayName != null || ep.key != null) { - return (T)(ep.children != null || ep.childrenEPName != null || ep.dynamic ? new CompositeWrapper(ep) : new ConfigurableWrapper(ep)); + if (ep.displayName != null || ep.key != null || ep.groupId != null) { + T configurable = null; + if (ep.providerClass != null) { + configurable = ep.createConfigurable(); + if (configurable == null) { + 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); } else { return ep.createConfigurable(); @@ -76,8 +85,9 @@ public class ConfigurableWrapper implements SearchableConfigurable { private final ConfigurableEP myEp; - private ConfigurableWrapper(@NotNull ConfigurableEP ep) { + private ConfigurableWrapper(@NotNull ConfigurableEP ep, @Nullable UnnamedConfigurable configurable) { myEp = ep; + myConfigurable = configurable; } private UnnamedConfigurable myConfigurable; @@ -95,6 +105,12 @@ public class ConfigurableWrapper implements SearchableConfigurable { @Nls @Override public String getDisplayName() { + if (myEp.displayName == null && myEp.key == null) { + UnnamedConfigurable configurable = getConfigurable(); + if (configurable instanceof Configurable) { + return ((Configurable)configurable).getDisplayName(); + } + } return myEp.getDisplayName(); } @@ -141,16 +157,24 @@ public class ConfigurableWrapper implements SearchableConfigurable { @NotNull @Override public String getId() { - return myEp.id == null ? myEp.instanceClass : myEp.id; + return myEp.id == null ? myEp.instanceClass == null ? myEp.providerClass : myEp.instanceClass : myEp.id; } + @NotNull + public ConfigurableEP getExtensionPoint() { + return myEp; + } + + public String getGroupId() { + return myEp.groupId; + } public String getParentId() { return myEp.parentId; } public ConfigurableWrapper addChild(Configurable configurable) { - return new CompositeWrapper(myEp, configurable); + return new CompositeWrapper(myEp, null, configurable); } @Override @@ -169,8 +193,8 @@ public class ConfigurableWrapper implements SearchableConfigurable { private Configurable[] myKids; - private CompositeWrapper(ConfigurableEP ep, Configurable... kids) { - super(ep); + private CompositeWrapper(@NotNull ConfigurableEP ep, @Nullable UnnamedConfigurable configurable, Configurable... kids) { + super(ep, configurable); if (ep.dynamic) { kids = ((Composite)getConfigurable()).getConfigurables(); } 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 new file mode 100644 index 000000000000..f465e2d0fecb --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java @@ -0,0 +1,83 @@ +/* + * 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 java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +public final class MixedConfigurableGroup implements 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]; + } + + private MixedConfigurableGroup(String groupId, HashMap<String, ArrayList<Configurable>> configurables) { + this(groupId, configurables.remove(groupId)); + } + + @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).getGroupId(); + } + ArrayList<Configurable> list = map.get(groupId); + if (list == null) { + map.put(groupId, list = new ArrayList<Configurable>()); + } + list.add(configurable); + } + 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()]); + } +} 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 bd843131e16a..5524df2bb2cb 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,19 @@ */ package com.intellij.openapi.options.newEditor; +import com.intellij.icons.AllIcons; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.openapi.Disposable; 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.options.ex.ConfigurableWrapper; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.*; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.treeStructure.*; @@ -287,7 +291,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl class Renderer extends GroupedElementsRenderer.Tree { - + private JLabel myProjectIcon; private JLabel myHandle; @Override @@ -304,6 +308,9 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl myHandle.setOpaque(false); content.add(myHandle, BorderLayout.WEST); content.add(myComponent, BorderLayout.CENTER); + myProjectIcon = new JLabel(" ", AllIcons.General.ProjectConfigurable, SwingConstants.LEFT); + myProjectIcon.setOpaque(true); + content.add(myProjectIcon, BorderLayout.EAST); myRendererComponent.add(content, BorderLayout.CENTER); } @@ -393,10 +400,39 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl myTextLabel.setForeground(selected ? UIUtil.getTreeSelectionForeground() : fg); myTextLabel.setOpaque(selected); + if (Registry.is("ide.file.settings.order.new")) { + myTextLabel.setBorder(new EmptyBorder(1,2,1,0)); + } + Project project = getConfigurableProject(base); + if (project != null && Registry.is("ide.file.settings.order.new")) { + myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground()); + myProjectIcon.setVisible(true); + tree.setToolTipText(OptionsBundle.message(project.isDefault() + ? "configurable.default.project.tooltip" + : "configurable.current.project.tooltip")); + } else { + myProjectIcon.setVisible(false); + tree.setToolTipText(null); + } return result; } + private Project getConfigurableProject(SimpleNode node) { + if (node == null) { + return null; + } + if (node instanceof EditorNode) { + EditorNode editor = (EditorNode)node; + Configurable configurable = editor.getConfigurable(); + if (configurable instanceof ConfigurableWrapper) { + ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable; + return wrapper.getExtensionPoint().getProject(); + } + } + return getConfigurableProject(node.getParent()); + } + protected JComponent createItemComponent() { myTextLabel = new ErrorLabel(); return myTextLabel; @@ -602,6 +638,12 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl private MyTree() { getInputMap().clear(); + setOpaque(true); + } + + @Override + protected boolean paintNodes() { + return false; } @Override 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 c79e4118f36c..2f95c21cb558 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 @@ -752,8 +752,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt message = ProjectBundle.message("project.reload.external.change.multiple", filesBuilder.toString()); } - return Messages.showTwoStepConfirmationDialog(message, ProjectBundle.message("project.reload.external.change.title"), "Reload project", - Messages.getQuestionIcon()) == 0; + return Messages.showDialog(message, + ProjectBundle.message("project.reload.external.change.title"), + new String[]{"&Reload Project", "&Discard Changes"}, + -1, + Messages.getQuestionIcon()) == 0; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form index 167e5ef8ab00..0e86badb08c5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form @@ -20,7 +20,7 @@ <grid id="3559e" binding="myPluginsPanel" layout-manager="BorderLayout" hgap="0" vgap="0"> <constraints> <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> - <gridbag top="3" left="0" bottom="3" right="0" weightx="1.0" weighty="0.0"/> + <gridbag top="3" left="0" bottom="3" right="0" weightx="1.0" weighty="1.0"/> </constraints> <properties> <autoscrolls value="false"/> @@ -41,12 +41,6 @@ <contentType value="text/html"/> </properties> </component> - <vspacer id="bf1d9"> - <constraints> - <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/> - <gridbag weightx="0.0" weighty="1.0"/> - </constraints> - </vspacer> </children> </grid> </form> diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index f7346548124a..8d00a82d4814 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -120,9 +120,6 @@ public class FileWatcher { } }); } - else if (!isUpToDate(myExecutable)) { - notifyOnFailure(ApplicationBundle.message("watcher.exe.outdated"), null); - } else { try { startupProcess(false); @@ -181,30 +178,16 @@ public class FileWatcher { @Nullable private static File getExecutable() { - String execPath = null; - - final String altExecPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH); - if (altExecPath != null && new File(altExecPath).isFile()) { - execPath = FileUtil.toSystemDependentName(altExecPath); - } + String execPath = System.getProperty(PROPERTY_WATCHER_EXECUTABLE_PATH); + if (execPath != null) return new File(execPath); - if (execPath == null) { - final String execName = getExecutableName(false); - if (execName == null) { - return null; - } - execPath = FileUtil.join(PathManager.getBinPath(), execName); - } + String execName = getExecutableName(false); + if (execName == null) return null; - File exec = new File(execPath); - if (!exec.exists()) { - String homePath = PathManager.getHomePath(); - if (new File(homePath, "community").exists()) { - homePath += File.separator + "community"; - } - exec = new File(FileUtil.join(homePath, "bin", getExecutableName(true))); - } - return exec; + return FileUtil.findFirstThatExist( + FileUtil.join(PathManager.getBinPath(), execName), + FileUtil.join(PathManager.getHomePath(), "community", "bin", getExecutableName(true)), + FileUtil.join(PathManager.getBinPath(), getExecutableName(true))); } @Nullable @@ -215,14 +198,6 @@ public class FileWatcher { return null; } - private static boolean isUpToDate(File executable) { - long length = SystemInfo.isWindows ? 71208 : - SystemInfo.isMac ? 13984 : - SystemInfo.isLinux ? SystemInfo.isAMD64 ? 29155 : 22791 : - -1; - return length < 0 || length == executable.length(); - } - public void notifyOnFailure(final String cause, @Nullable final NotificationListener listener) { LOG.warn(cause); @@ -580,8 +555,11 @@ public class FileWatcher { case CREATE: case DELETE: for (String p : paths) { + myDirtyPaths.dirtyPaths.add(p); String parentPath = new File(p).getParent(); - myDirtyPaths.dirtyPaths.add(parentPath != null ? parentPath : p); + if (parentPath != null) { + myDirtyPaths.dirtyPaths.add(parentPath); + } } break; 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 72cd066472c6..b05b7a285e7b 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 @@ -1338,7 +1338,11 @@ public class FSRecords implements Forceable { private static final MessageDigest myDigest = ContentHashesUtil.createHashDigest(); public static void writeContent(int fileId, ByteSequence bytes, boolean readOnly) throws IOException { - new ContentOutputStream(fileId, readOnly).writeBytes(bytes); + try { + new ContentOutputStream(fileId, readOnly).writeBytes(bytes); + } catch (Throwable e) { + throw DbConnection.handleError(e); + } } public static int storeUnlinkedContent(byte[] bytes) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java index 36a79f23cf89..c302cce7572e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java @@ -195,7 +195,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { @Override @NotNull public ActionCallback requestFocus(@NotNull final Component c, final boolean forced) { - return requestFocus(new FocusCommand.ByComponent(c), forced); + return requestFocus(new FocusCommand.ByComponent(c, new Exception()), forced); } @Override @@ -1148,7 +1148,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable { } if (toFocus != null) { - return requestFocus(new FocusCommand.ByComponent(toFocus).setToInvalidateRequestors(false), forced); + return requestFocus(new FocusCommand.ByComponent(toFocus, new Exception()).setToInvalidateRequestors(false), forced); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java index 7d534d5be545..f62ff2c1819a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java @@ -30,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.ui.MouseDragHelper; import com.intellij.ui.PopupHandler; +import com.intellij.util.ui.JBImageIcon; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -183,12 +184,22 @@ public final class StripeButton extends AnchoredButton implements ActionListener if (myDragPane == null) return; final BufferedImage image = UIUtil.createImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); paint(image.getGraphics()); - myDragButtonImage = new JLabel(new ImageIcon(image)) { + myDragButtonImage = new JLabel(new JBImageIcon(image)) { public String toString() { return "Image for: " + StripeButton.this.toString(); } }; + + myDragButtonImage.addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + finishDragging(); + myPressedPoint = null; + myDragButtonImage = null; + super.mouseReleased(e); + } + }); myDragPane.add(myDragButtonImage, JLayeredPane.POPUP_LAYER); myDragButtonImage.setSize(myDragButtonImage.getPreferredSize()); setVisible(false); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java index b2fc056d0a71..aa7d022a4b5e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.BalloonHandler; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.StatusBar; @@ -38,14 +39,16 @@ import javax.swing.event.HyperlinkListener; import java.awt.*; import java.awt.event.ComponentEvent; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @author Anton Katilin * @author Vladimir Kondratyev */ public final class TestWindowManager extends WindowManagerEx { - private static final StatusBarEx ourStatusBar = new DummyStatusBar(); + private static final Key<StatusBar> STATUS_BAR = Key.create("STATUS_BAR"); public final void doNotSuggestAsParent(final Window window) { } @@ -66,7 +69,13 @@ public final class TestWindowManager extends WindowManagerEx { @Override public final StatusBar getStatusBar(final Project project) { - return ourStatusBar; + synchronized (STATUS_BAR) { + StatusBar statusBar = project.getUserData(STATUS_BAR); + if (statusBar == null) { + project.putUserData(STATUS_BAR, statusBar = new DummyStatusBar()); + } + return statusBar; + } } @Override @@ -86,6 +95,8 @@ public final class TestWindowManager extends WindowManagerEx { public void resetWindow(final Window window) { } private static final class DummyStatusBar implements StatusBarEx { + private final Map<String, StatusBarWidget> myWidgetMap = new HashMap<String, StatusBarWidget>(); + @Override public Dimension getSize() { return new Dimension(0, 0); @@ -140,33 +151,39 @@ public final class TestWindowManager extends WindowManagerEx { } @Override + public void addWidget(@NotNull StatusBarWidget widget) { + myWidgetMap.put(widget.ID(), widget); + } + + @Override + public void addWidget(@NotNull StatusBarWidget widget, @NotNull String anchor) { + addWidget(widget); + } + + @Override public void addWidget(@NotNull StatusBarWidget widget, @NotNull Disposable parentDisposable) { Disposer.register(parentDisposable, widget); + addWidget(widget); } @Override public void addWidget(@NotNull StatusBarWidget widget, @NotNull String anchor, @NotNull Disposable parentDisposable) { Disposer.register(parentDisposable, widget); + addWidget(widget); } @Override public void updateWidgets() { } @Override - public void addWidget(@NotNull StatusBarWidget widget) { } - - @Override public void dispose() { } @Override - public void addWidget(@NotNull StatusBarWidget widget, @NotNull String anchor) { } - - @Override public void updateWidget(@NotNull String id) { } @Override public StatusBarWidget getWidget(String id) { - return null; + return myWidgetMap.get(id); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index ae1e5336e9fe..efcdd148d57b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -357,7 +357,7 @@ public final class ToolWindowImpl implements ToolWindowEx { ApplicationManager.getApplication().assertIsDispatchThread(); final Icon oldIcon = getIcon(); if (oldIcon != icon && !(icon instanceof LayeredIcon) && (icon.getIconHeight() != 13 || icon.getIconWidth() != 13)) { - LOG.warn("ToolWindow icons should be 13x13. Please fix " + icon); + LOG.warn("ToolWindow icons should be 13x13. Please fix ToolWindow (ID: " + getId() + ") or icon " + icon); } getSelectedContent().setIcon(icon); myIcon = icon; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInToolWindowCmd.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInToolWindowCmd.java index d58d3b914849..c8f542133149 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInToolWindowCmd.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInToolWindowCmd.java @@ -184,7 +184,7 @@ public final class RequestFocusInToolWindowCmd extends FinalizableCommand { }).notify(result); } else { - myManager.getFocusManager().requestFocus(new FocusCommand.ByComponent(c, myToolWindow.getComponent()), myForced) + myManager.getFocusManager().requestFocus(new FocusCommand.ByComponent(c, myToolWindow.getComponent(), new Exception()), myForced) .doWhenProcessed(new Runnable() { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 84b6e6a7e0ce..e00c195be9ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -368,7 +368,8 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge myRefreshAndInfoPanel.revalidate(); myRefreshAndInfoPanel.repaint(); - if (UISettings.getInstance().PRESENTATION_MODE) { + UISettings uiSettings = UISettings.getInstance(); + if (uiSettings.PRESENTATION_MODE || !uiSettings.SHOW_STATUS_BAR && Registry.is("ide.show.progress.without.status.bar")) { final JRootPane pane = myInfoPanel.getRootPane(); final RelativePoint point = new RelativePoint(pane, new Point(pane.getWidth() - 250, 60)); final PresentationModeProgressPanel panel = new PresentationModeProgressPanel(inline); diff --git a/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java b/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java index 2d4a76f1df1c..4e5482d3d422 100644 --- a/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java +++ b/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java @@ -5,7 +5,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.Sdk; import com.intellij.util.PathMappingSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,8 +32,4 @@ public abstract class PathMappingProvider { @NotNull public abstract PathMappingSettings getPathMappingSettings(@NotNull Project project, @NotNull RemoteSdkAdditionalData data); - - @Deprecated //Remove in IDEA 14 - @NotNull - public abstract PathMappingSettings getPathMapping(@NotNull Project project, @NotNull com.intellij.remotesdk.RemoteSdkAdditionalData data); } diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteFile.java b/platform/platform-impl/src/com/intellij/remote/RemoteFile.java index 4a2e11379364..724ec31fe1ef 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteFile.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteFile.java @@ -2,7 +2,6 @@ package com.intellij.remote; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author traff @@ -25,14 +24,14 @@ public class RemoteFile { this(resolveChild(parent, child, isWin), isWin); } - @Nullable + @NotNull public String getName() { int ind = myPath.lastIndexOf(getSeparator(myWin)); if (ind != -1 && ind < myPath.length() - 1) { //not last char return myPath.substring(ind + 1); } else { - return null; + return myPath; } } @@ -88,6 +87,10 @@ public class RemoteFile { return detectSystemByPath(path).createRemoteFile(path, script); } + public static RemoteFile createRemoteFile(String path) { + return detectSystemByPath(path).createRemoteFile(path); + } + public static RemoteFile createRemoteFile(final String path, final String script, final boolean isWindows) { return new RemoteFileBuilder(isWindows).createRemoteFile(path, script); } diff --git a/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java b/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java deleted file mode 100644 index 0b630fec6a8b..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/MutableRemoteCredentials.java +++ /dev/null @@ -1,23 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * @author traff - */ -public interface MutableRemoteCredentials extends com.intellij.remote.MutableRemoteCredentials { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java deleted file mode 100644 index 2a249209b8e8..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCancelledException.java +++ /dev/null @@ -1,27 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public class RemoteCancelledException extends com.intellij.remote.RemoteCancelledException { - public RemoteCancelledException(String s) { - super(s); - } -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java deleted file mode 100644 index e6be766ca826..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentials.java +++ /dev/null @@ -1,24 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public interface RemoteCredentials extends com.intellij.remote.RemoteCredentials { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java deleted file mode 100644 index 886052957f32..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteCredentialsHolder.java +++ /dev/null @@ -1,24 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public class RemoteCredentialsHolder extends com.intellij.remote.RemoteCredentialsHolder { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java deleted file mode 100644 index 73274cc0f356..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteFile.java +++ /dev/null @@ -1,38 +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.remotesdk; - -import org.jetbrains.annotations.NotNull; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public class RemoteFile extends com.intellij.remote.RemoteFile { - - public RemoteFile(@NotNull String path, boolean isWin) { - super(path, isWin); - } - - public RemoteFile(@NotNull String parent, String child) { - super(parent, child); - } - - public RemoteFile(@NotNull String parent, String child, boolean isWin) { - super(parent, child, isWin); - } -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java deleted file mode 100644 index a83d2bdc2455..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteProcessHandlerBase.java +++ /dev/null @@ -1,24 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public interface RemoteProcessHandlerBase extends com.intellij.remote.RemoteProcessHandlerBase { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java deleted file mode 100644 index e4c79ed8d7f2..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkAdditionalData.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.intellij.remotesdk; - -import com.intellij.openapi.projectRoots.SdkAdditionalData; -import com.intellij.remote.RemoteSdkCredentials; - -/** - * @deprecated Remove in IDEA 14 - * @author traff - */ -public interface RemoteSdkAdditionalData extends RemoteSdkCredentials, SdkAdditionalData { - void completeInitialization(); -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java deleted file mode 100644 index d99ea338db00..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java +++ /dev/null @@ -1,26 +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.remotesdk; - -import com.intellij.remote.RemoteSdkCredentials; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public interface RemoteSdkData extends RemoteSdkCredentials { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java deleted file mode 100644 index f2dd26589392..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataBuilder.java +++ /dev/null @@ -1,26 +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.remotesdk; - -import com.intellij.remote.RemoteSdkCredentialsBuilder; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public class RemoteSdkDataBuilder extends RemoteSdkCredentialsBuilder { -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java deleted file mode 100644 index b4f837c72a3f..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java +++ /dev/null @@ -1,30 +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.remotesdk; - -import com.intellij.remote.RemoteSdkCredentialsHolder; -import org.jetbrains.annotations.NotNull; - -/** - * @deprecated Remove in IDEA 14 - * - * @author traff - */ -public class RemoteSdkDataHolder extends RemoteSdkCredentialsHolder { - public RemoteSdkDataHolder(@NotNull String defaultHelpersDirName) { - super(defaultHelpersDirName); - } -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java deleted file mode 100644 index 1934d1aa36a2..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkFactory.java +++ /dev/null @@ -1,45 +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.remotesdk; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.remote.RemoteSdkException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; -import java.util.Collection; - -/** - * @deprecated Remove in IDEA 14 - * @author traff - */ -public interface RemoteSdkFactory<T extends RemoteSdkAdditionalData> { - Sdk createRemoteSdk(@Nullable Project project, @NotNull T data, @Nullable String sdkName, Collection<Sdk> existingSdks) - throws RemoteInterpreterException; - - Sdk createUnfinished(T data, Collection<Sdk> existingSdks); - - String getDefaultUnfinishedName(); - - @NotNull - String sdkName(); - - boolean canSaveUnfinished(); - - void initSdk(@NotNull Sdk sdk, @Nullable Project project, @Nullable Component ownerComponent); -} diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java deleted file mode 100644 index 3abe39bd1aba..000000000000 --- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSshProcess.java +++ /dev/null @@ -1,23 +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.remotesdk; - -/** - * @deprecated Remove in IDEA 14 - * @author traff - */ -public abstract class RemoteSshProcess extends com.intellij.remote.RemoteSshProcess { -} diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index 7226ee84e0c6..4e65063e7939 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -54,6 +54,16 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte myTipComponent = new TipComponent(); + myTipComponent.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + // don't hide the hint if mouse exited to myComponent + if (myComponent.getMousePosition() == null) { + hideHint(); + } + } + }); + myComponent.addMouseListener( new MouseListener() { @Override @@ -63,7 +73,10 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte @Override public void mouseExited(MouseEvent e) { - hideHint(); + // don't hide the hint if mouse exited to it + if (myTipComponent.getMousePosition() == null) { + hideHint(); + } } @Override @@ -319,7 +332,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte g.setClip(null); doFillBackground(height, width, g); g.translate(-(visibleRect.x + visibleRect.width - cellBounds.x), 0); - doPaintTooltipImage(renderer, cellBounds, height, g, key); + doPaintTooltipImage(renderer, cellBounds, g, key); if (isPaintBorder()) { g.translate(visibleRect.x + visibleRect.width - cellBounds.x, 0); @@ -354,8 +367,8 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte g.fillRect(0, 0, width, height); } - protected void doPaintTooltipImage(Component rComponent, Rectangle cellBounds, int height, Graphics2D g, KeyType key) { - myRendererPane.paintComponent(g, rComponent, myComponent, 0, 0, cellBounds.width, height, true); + protected void doPaintTooltipImage(Component rComponent, Rectangle cellBounds, Graphics2D g, KeyType key) { + myRendererPane.paintComponent(g, rComponent, myComponent, 0, 0, cellBounds.width, cellBounds.height, true); } protected Rectangle getVisibleRect(KeyType key) { diff --git a/platform/platform-impl/src/com/intellij/ui/CellRendererPanel.java b/platform/platform-impl/src/com/intellij/ui/CellRendererPanel.java index 2c33b7cd1b61..653aba26dae8 100644 --- a/platform/platform-impl/src/com/intellij/ui/CellRendererPanel.java +++ b/platform/platform-impl/src/com/intellij/ui/CellRendererPanel.java @@ -25,6 +25,9 @@ import java.awt.*; * @author gregsh */ public class CellRendererPanel extends JPanel { + public CellRendererPanel() { + super(null); // we do the layout ourselves + } // property change support ---------------- protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { @@ -46,7 +49,10 @@ public class CellRendererPanel extends JPanel { @Override public void doLayout() { if (getComponentCount() != 1) return; - getComponent(0).setBounds(0, 0, getWidth(), getHeight()); + Insets insets = getInsets(); + getComponent(0).setBounds(insets.left, insets.top, + getWidth() - insets.left - insets.right, + getHeight() - insets.top - insets.bottom); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/ColorChooserServiceImpl.java b/platform/platform-impl/src/com/intellij/ui/ColorChooserServiceImpl.java index 4bc4213a78ec..355c2a8de3e3 100644 --- a/platform/platform-impl/src/com/intellij/ui/ColorChooserServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/ColorChooserServiceImpl.java @@ -15,10 +15,11 @@ */ package com.intellij.ui; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.Arrays; +import java.util.List; /** * @author Konstantin Bulenkov @@ -31,7 +32,7 @@ public class ColorChooserServiceImpl extends ColorChooserService { Color preselectedColor, boolean enableOpacity, ColorPickerListener[] listeners) { - return ColorPicker.showDialog(parent, caption, preselectedColor, enableOpacity, listeners, false); + return showDialog(parent, caption, preselectedColor, enableOpacity, Arrays.asList(listeners), false); } @Nullable @@ -42,6 +43,17 @@ public class ColorChooserServiceImpl extends ColorChooserService { boolean enableOpacity, ColorPickerListener[] listeners, boolean opacityInPercent) { + return showDialog(parent, caption, preselectedColor, enableOpacity, Arrays.asList(listeners), opacityInPercent); + } + + @Nullable + @Override + public Color showDialog(Component parent, + String caption, + Color preselectedColor, + boolean enableOpacity, + List<ColorPickerListener> listeners, + boolean opacityInPercent) { return ColorPicker.showDialog(parent, caption, preselectedColor, enableOpacity, listeners, opacityInPercent); } } diff --git a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java index d78e68137df1..e7b93684ace8 100644 --- a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java +++ b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java @@ -46,6 +46,7 @@ import java.awt.image.ImageObserver; import java.awt.image.MemoryImageSource; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -64,7 +65,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private final JTextField myBlue; private final JTextField myHex; private final Alarm myUpdateQueue; - private final ColorPickerListener[] myExternalListeners; + private final List<ColorPickerListener> myExternalListeners; private final boolean myOpacityInPercent; @@ -88,13 +89,13 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen }; public ColorPicker(@NotNull Disposable parent, @Nullable Color color, boolean enableOpacity) { - this(parent, color, true, enableOpacity, new ColorPickerListener[0], false); + this(parent, color, true, enableOpacity, Collections.<ColorPickerListener>emptyList(), false); } private ColorPicker(Disposable parent, @Nullable Color color, boolean restoreColors, boolean enableOpacity, - ColorPickerListener[] listeners, boolean opacityInPercent) { + List<ColorPickerListener> listeners, boolean opacityInPercent) { myUpdateQueue = new Alarm(Alarm.ThreadToUse.SWING_THREAD, parent); myRed = createColorField(false); myGreen = createColorField(false); @@ -332,7 +333,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen String caption, Color preselectedColor, boolean enableOpacity, - ColorPickerListener[] listeners, + List<ColorPickerListener> listeners, boolean opacityInPercent) { final ColorPickerDialog dialog = new ColorPickerDialog(parent, caption, preselectedColor, enableOpacity, listeners, opacityInPercent); dialog.show(); @@ -884,7 +885,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen static class ColorPickerDialog extends DialogWrapper { private final Color myPreselectedColor; - private final ColorPickerListener[] myListeners; + private final List<ColorPickerListener> myListeners; private ColorPicker myColorPicker; private final boolean myEnableOpacity; private ColorPipette myPicker; @@ -894,7 +895,7 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen String caption, @Nullable Color preselectedColor, boolean enableOpacity, - ColorPickerListener[] listeners, + List<ColorPickerListener> listeners, boolean opacityInPercent) { super(parent, true); myListeners = listeners; diff --git a/platform/platform-impl/src/com/intellij/ui/ColorPickerListenerFactory.java b/platform/platform-impl/src/com/intellij/ui/ColorPickerListenerFactory.java index 6f1c0479eeca..dbed5e5abb24 100644 --- a/platform/platform-impl/src/com/intellij/ui/ColorPickerListenerFactory.java +++ b/platform/platform-impl/src/com/intellij/ui/ColorPickerListenerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,29 +17,32 @@ package com.intellij.ui; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; -import com.intellij.util.Function; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -/** - * User: ksafonov - */ public abstract class ColorPickerListenerFactory { private static final ExtensionPointName<ColorPickerListenerFactory> EP_NAME = ExtensionPointName.create("com.intellij.colorPickerListenerFactory"); - public static ColorPickerListener[] createListenersFor(@Nullable final PsiElement element) { - final List<ColorPickerListener> listeners = - ContainerUtil.mapNotNull(EP_NAME.getExtensions(), new Function<ColorPickerListenerFactory, ColorPickerListener>() { - @Override - public ColorPickerListener fun(ColorPickerListenerFactory factory) { - return factory.createListener(element); + @NotNull + public static List<ColorPickerListener> createListenersFor(@Nullable PsiElement element) { + List<ColorPickerListener> listeners = null; + for (ColorPickerListenerFactory factory : EP_NAME.getExtensions()) { + ColorPickerListener listener = factory.createListener(element); + if (listener != null) { + if (listeners == null) { + listeners = new SmartList<ColorPickerListener>(); } - }); - return listeners.toArray(new ColorPickerListener[listeners.size()]); + listeners.add(listener); + } + } + return ContainerUtil.notNullize(listeners); } + @Nullable public abstract ColorPickerListener createListener(@Nullable PsiElement element); } diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java index e803fa5fd63d..d11e990f8dba 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java @@ -57,39 +57,39 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, protected abstract EditorColorsScheme getColorScheme(); - protected abstract String getText(JTable table, Object value, int row, int column); + protected abstract String getText(FontMetrics fontMetrics, JTable table, Object value, int row, int column); protected void customizeEditor(EditorEx editor, Object value, boolean selected, int row, int col) { } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - String text = getText(table, value, row, column); MyPanel panel = getEditorPanel(table); EditorEx editor = panel.editor; int tableFontSize = table.getFont().getSize(); if (editor.getColorsScheme().getEditorFontSize() != tableFontSize) { editor.getColorsScheme().setEditorFontSize(tableFontSize); } - setText(editor, text); - - if (isSelected) { - ((EditorImpl)editor).setPaintSelection(true); - editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground()); - editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground()); - editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength()); - editor.setBackgroundColor(table.getSelectionBackground()); - } - else { - ((EditorImpl)editor).setPaintSelection(false); - editor.getSelectionModel().setSelection(0, 0); - boolean selectedRow = table.getSelectedRowCount() > 0 && table.getSelectedRows()[table.getSelectedRowCount() - 1] == row; - editor.setBackgroundColor(!selectedRow ? table.getBackground() : getColorScheme().getColor(EditorColors.CARET_ROW_COLOR)); - } + setText(editor, getText(((EditorImpl)editor).getFontMetrics(Font.PLAIN), table, value, row, column)); + + ((EditorImpl)editor).setPaintSelection(isSelected); + editor.getSelectionModel().setSelection(0, isSelected ? editor.getDocument().getTextLength() : 0); + editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground()); + editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground()); + editor.setBackgroundColor(getCellBackgroundColor(getColorScheme(), table, isSelected, row)); + + panel.setBorder(null); // prevents double border painting when ExtendedItemRendererComponentWrapper is used + customizeEditor(editor, value, isSelected, row, column); return panel; } + public static Color getCellBackgroundColor(EditorColorsScheme colorsScheme, JTable table, boolean isSelected, int row) { + return isSelected ? table.getSelectionBackground() : + table.getSelectionModel().getLeadSelectionIndex() == row ? colorsScheme.getColor(EditorColors.CARET_ROW_COLOR) : + table.getBackground(); + } + @NotNull private MyPanel getEditorPanel(JTable table) { MyPanel panel = (MyPanel)table.getClientProperty(MY_PANEL_PROPERTY); @@ -142,6 +142,16 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } @Override + protected void paintComponent(Graphics g) { + if (getBorder() == null) return; + Color oldColor = g.getColor(); + Rectangle clip = g.getClipBounds(); + g.setColor(editor.getBackgroundColor()); + g.fillRect(clip.x, clip.y, clip.width, clip.height); + g.setColor(oldColor); + } + + @Override public void dispose() { EditorFactory.getInstance().releaseEditor(editor); } diff --git a/platform/platform-impl/src/com/intellij/ui/ShowColorPickerAction.java b/platform/platform-impl/src/com/intellij/ui/ShowColorPickerAction.java index 95f4b7e33861..5327c84c3c8d 100644 --- a/platform/platform-impl/src/com/intellij/ui/ShowColorPickerAction.java +++ b/platform/platform-impl/src/com/intellij/ui/ShowColorPickerAction.java @@ -18,12 +18,12 @@ package com.intellij.ui; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.WindowManager; import javax.swing.*; +import java.util.List; /** * @author Konstantin Bulenkov @@ -34,9 +34,8 @@ public class ShowColorPickerAction extends AnAction { final Project project = e.getProject(); JComponent root = rootComponent(project); if (root != null) { - ColorPickerListener[] listeners = ColorPickerListenerFactory.createListenersFor(e.getData(CommonDataKeys.PSI_ELEMENT)); - final ColorPicker.ColorPickerDialog picker = - new ColorPicker.ColorPickerDialog(root, "Color Picker", null, true, listeners, true); + List<ColorPickerListener> listeners = ColorPickerListenerFactory.createListenersFor(e.getData(CommonDataKeys.PSI_ELEMENT)); + ColorPicker.ColorPickerDialog picker = new ColorPicker.ColorPickerDialog(root, "Color Picker", null, true, listeners, true); picker.setModal(false); picker.show(); } diff --git a/platform/platform-impl/src/com/intellij/ui/Splash.java b/platform/platform-impl/src/com/intellij/ui/Splash.java index 0f4147f61753..023cef7bac06 100644 --- a/platform/platform-impl/src/com/intellij/ui/Splash.java +++ b/platform/platform-impl/src/com/intellij/ui/Splash.java @@ -44,6 +44,7 @@ import java.util.List; */ public class Splash extends JDialog implements StartupProgress { @Nullable public static Rectangle BOUNDS; + private final Icon myImage; private int myProgressHeight = 2; private Color myProgressColor = null; @@ -84,8 +85,16 @@ public class Splash extends JDialog implements StartupProgress { } private void setLocationInTheCenterOfScreen() { - Rectangle deviceBounds = getGraphicsConfiguration().getBounds(); - setLocation((deviceBounds.width - getWidth()) / 2, (deviceBounds.height - getHeight()) / 2); + Rectangle bounds = getGraphicsConfiguration().getBounds(); + if (SystemInfo.isWindows) { + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration()); + int x = insets.left + (bounds.width - insets.left - insets.right - getWidth()) / 2; + int y = insets.top + (bounds.height - insets.top - insets.bottom - getHeight()) / 2; + setLocation(x, y); + } + else { + setLocation((bounds.width - getWidth()) / 2, (bounds.height - getHeight()) / 2); + } } public Splash(ApplicationInfoEx info) { diff --git a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java index af4707c60ec3..b7704a687441 100644 --- a/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/TableExpandableItemsHandler.java @@ -106,22 +106,12 @@ public class TableExpandableItemsHandler extends AbstractExpandableItemsHandler< } public Pair<Component, Rectangle> getCellRendererAndBounds(TableCell key) { - Rectangle cellRect = getCellRect(key); - - int modelColumnIndex = myComponent.convertColumnIndexToModel(key.column); - final int modelRowIndex = myComponent.convertRowIndexToModel(key.row); - TableModel model = myComponent.getModel(); - if (key.row < 0 || key.row >= model.getRowCount() || key.column < 0 || key.column >= model.getColumnCount()) { + if (key.row < 0 || key.row >= myComponent.getRowCount() || key.column < 0 || key.column >= myComponent.getColumnCount()) { return null; } - Component renderer = myComponent - .getCellRenderer(key.row, key.column) - .getTableCellRendererComponent(myComponent, - model.getValueAt(modelRowIndex, modelColumnIndex), - myComponent.getSelectionModel().isSelectedIndex(key.row), - myComponent.hasFocus(), - key.row, key.column); + Rectangle cellRect = getCellRect(key); + Component renderer = myComponent.prepareRenderer(myComponent.getCellRenderer(key.row, key.column), key.row, key.column); cellRect.width = renderer.getPreferredSize().width; return Pair.create(renderer, cellRect); diff --git a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java index 93a9d9390d33..b596204e6ad2 100644 --- a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java +++ b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java @@ -55,7 +55,9 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> { @Override protected boolean isSpeedSearchEnabled() { - return !getComponent().isEditing() && super.isSpeedSearchEnabled(); + JTable table = getComponent(); + boolean tableIsNotEmpty = table.getRowCount() != 0 && table.getColumnCount() != 0; + return tableIsNotEmpty && !table.isEditing() && super.isSpeedSearchEnabled(); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java index ad5466267dba..b24e10b943f4 100644 --- a/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java @@ -148,7 +148,6 @@ public class TreeExpandableItemsHandler extends AbstractExpandableItemsHandler<I @Override protected void doPaintTooltipImage(final Component rComponent, final Rectangle cellBounds, - final int height, final Graphics2D g, Integer key) { final boolean opaque = rComponent.isOpaque(); @@ -169,7 +168,7 @@ public class TreeExpandableItemsHandler extends AbstractExpandableItemsHandler<I rComponent.setBackground(bg); } - super.doPaintTooltipImage(rComponent, cellBounds, height, g, key); + super.doPaintTooltipImage(rComponent, cellBounds, g, key); if (rComponent instanceof JComponent) { ((JComponent)rComponent).setOpaque(opaque); 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 6ce0375e75aa..2a70b61c6e8a 100644 --- a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java +++ b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java @@ -73,10 +73,14 @@ public class JBMacMessages extends MacMessagesEmulation { Icon icon = errorStyle ? UIUtil.getErrorIcon() : UIUtil.getInformationIcon(); - focusedOptionIndex = (defaultOptionIndex == focusedOptionIndex) ? buttons.length - 1 : focusedOptionIndex; + if (focusedOptionIndex != -1) { + focusedOptionIndex = (defaultOptionIndex == focusedOptionIndex) ? buttons.length - 1 : focusedOptionIndex; + } + + final String defaultOptionTitle = defaultOptionIndex == -1 ? null : buttons[defaultOptionIndex]; + final String focusedButtonTitle = focusedOptionIndex == -1 ? null : buttons[focusedOptionIndex]; - SheetMessage sheetMessage = new SheetMessage(window, title, message, icon, buttons, doNotAskDialogOption, buttons[defaultOptionIndex], - buttons[focusedOptionIndex]); + final SheetMessage sheetMessage = new SheetMessage(window, title, message, icon, buttons, doNotAskDialogOption, defaultOptionTitle, focusedButtonTitle); String result = sheetMessage.getResult(); for (int i = 0; i < buttons.length; i++) { if (result.equals(buttons[i])) { diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index e1c326d33cd8..78802ccdf6bb 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -337,7 +337,7 @@ public class AbstractPopup implements JBPopup { } public void setShowHints(boolean show) { - final Window ancestor = SwingUtilities.getWindowAncestor(myComponent); + final Window ancestor = getContentWindow(myComponent); if (ancestor instanceof RootPaneContainer) { final JRootPane rootPane = ((RootPaneContainer)ancestor).getRootPane(); if (rootPane != null) { @@ -757,7 +757,33 @@ public class AbstractPopup implements JBPopup { PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog); myNativePopup = factory.isNativePopup(); - myPopup = factory.getPopup(myOwner, myContent, targetBounds.x, targetBounds.y, this); + Component popupOwner = myOwner; + if (popupOwner instanceof RootPaneContainer) { + // JDK uses cached heavyweight popup for a window ancestor + RootPaneContainer root = (RootPaneContainer)popupOwner; + popupOwner = root.getRootPane(); + } + if (LOG.isDebugEnabled()) { + LOG.debug("expected preferred size: " + myContent.getPreferredSize()); + } + myPopup = factory.getPopup(popupOwner, myContent, targetBounds.x, targetBounds.y, this); + if (LOG.isDebugEnabled()) { + LOG.debug(" actual preferred size: " + myContent.getPreferredSize()); + } + if ((targetBounds.width != myContent.getWidth()) || (targetBounds.height != myContent.getHeight())) { + // JDK uses cached heavyweight popup that is not initialized properly + LOG.debug("the expected size is not equal to the actual size"); + Window popup = myPopup.getWindow(); + if (popup != null) { + popup.setSize(targetBounds.width, targetBounds.height); + if (myContent.getParent().getComponentCount() != 1) { + LOG.debug("unexpected count of components in heavy-weight popup"); + } + } + else { + LOG.debug("cannot fix size for non-heavy-weight popup"); + } + } if (myResizable) { final JRootPane root = myContent.getRootPane(); @@ -799,13 +825,10 @@ public class AbstractPopup implements JBPopup { listener.beforeShown(new LightweightWindowEvent(this)); } - // can be improved by moving in myPopup code - myPopup.getWindow().setSize(myContent.getSize()); - myPopup.setRequestFocus(myRequestFocus); myPopup.show(); - final Window window = SwingUtilities.getWindowAncestor(myContent); + final Window window = getContentWindow(myContent); myWindow = window; @@ -1185,14 +1208,17 @@ public class AbstractPopup implements JBPopup { size = computeWindowSize(size); - final Window window = SwingUtilities.getWindowAncestor(myContent); - window.setSize(size); + final Window window = getContentWindow(myContent); + if (window != null) { + window.setSize(size); + } } public void pack() { - final Window window = SwingUtilities.getWindowAncestor(myContent); - - window.pack(); + final Window window = getContentWindow(myContent); + if (window != null) { + window.pack(); + } } public JComponent getComponent() { @@ -1211,6 +1237,10 @@ public class AbstractPopup implements JBPopup { } myDisposed = true; + if (LOG.isDebugEnabled()) { + LOG.debug("start disposing " + myContent); + } + Disposer.dispose(this, false); ApplicationManager.getApplication().assertIsDispatchThread(); @@ -1257,6 +1287,10 @@ public class AbstractPopup implements JBPopup { IdeFocusManager.getInstance(myProject).typeAheadUntil(typeAheadDone); getFocusManager().doWhenFocusSettlesDown(runFinal); } + + if (LOG.isDebugEnabled()) { + LOG.debug("stop disposing content"); + } } private void resetWindow() { @@ -1385,15 +1419,27 @@ public class AbstractPopup implements JBPopup { } public static Window moveTo(JComponent content, Point screenPoint, final Dimension headerCorrectionSize) { - setDefaultCursor(content); - final Window wnd = SwingUtilities.getWindowAncestor(content); - if (headerCorrectionSize != null) { - screenPoint.y -= headerCorrectionSize.height; + final Window wnd = getContentWindow(content); + if (wnd != null) { + wnd.setCursor(Cursor.getDefaultCursor()); + if (headerCorrectionSize != null) { + screenPoint.y -= headerCorrectionSize.height; + } + wnd.setLocation(screenPoint); } - wnd.setLocation(screenPoint); return wnd; } + private static Window getContentWindow(Component content) { + Window window = SwingUtilities.getWindowAncestor(content); + if (window == null) { + if (LOG.isDebugEnabled()) { + LOG.debug("no window ancestor for " + content); + } + } + return window; + } + @Override public Point getLocationOnScreen() { Dimension headerCorrectionSize = myLocateByContent ? myHeaderPanel.getPreferredSize() : null; @@ -1467,7 +1513,7 @@ public class AbstractPopup implements JBPopup { } public static void setDefaultCursor(JComponent content) { - final Window wnd = SwingUtilities.getWindowAncestor(content); + final Window wnd = getContentWindow(content); if (wnd != null) { wnd.setCursor(Cursor.getDefaultCursor()); } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java index c7194ca5b4c4..2d7a8e3fb276 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupFactoryImpl.java @@ -227,8 +227,11 @@ public class PopupFactoryImpl extends JBPopupFactory { Presentation presentation = new Presentation(); presentation.setDescription(action.getTemplatePresentation().getDescription()); final String actualActionPlace = actionPlace == null ? ActionPlaces.UNKNOWN : actionPlace; - action.update(new AnActionEvent(null, DataManager.getInstance().getDataContext(myComponent), actualActionPlace, presentation, - ActionManager.getInstance(), 0)); + final AnActionEvent actionEvent = + new AnActionEvent(null, DataManager.getInstance().getDataContext(myComponent), actualActionPlace, presentation, + ActionManager.getInstance(), 0); + actionEvent.setInjectedContext(action.isInInjectedContext()); + action.update(actionEvent); ActionMenu.showDescriptionInStatusBar(true, myComponent, presentation.getDescription()); } }); @@ -730,7 +733,10 @@ public class PopupFactoryImpl extends JBPopupFactory { myFinalRunnable = new Runnable() { @Override public void run() { - action.actionPerformed(new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, action.getTemplatePresentation().clone(), ActionManager.getInstance(), eventModifiers)); + final AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, action.getTemplatePresentation().clone(), + ActionManager.getInstance(), eventModifiers); + event.setInjectedContext(action.isInInjectedContext()); + action.actionPerformed(event); } }; return FINAL_CHOICE; @@ -879,7 +885,10 @@ public class PopupFactoryImpl extends JBPopupFactory { @NotNull private AnActionEvent createActionEvent(@NotNull AnAction actionGroup) { - return new AnActionEvent(null, myDataContext, myActionPlace, getPresentation(actionGroup), ActionManager.getInstance(), 0); + final AnActionEvent actionEvent = + new AnActionEvent(null, myDataContext, myActionPlace, getPresentation(actionGroup), ActionManager.getInstance(), 0); + actionEvent.setInjectedContext(actionGroup.isInInjectedContext()); + return actionEvent; } private void appendActionsFromGroup(@NotNull ActionGroup actionGroup) { diff --git a/platform/platform-impl/src/com/intellij/ui/popup/list/GroupedItemsListRenderer.java b/platform/platform-impl/src/com/intellij/ui/popup/list/GroupedItemsListRenderer.java index 72f2e1dc3b37..9383f5c3f08e 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/list/GroupedItemsListRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/list/GroupedItemsListRenderer.java @@ -18,9 +18,7 @@ package com.intellij.ui.popup.list; import com.intellij.openapi.ui.popup.ListItemDescriptor; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.EngravedLabel; import com.intellij.ui.ErrorLabel; -import com.intellij.ui.Gray; import com.intellij.ui.GroupedElementsRenderer; import com.intellij.ui.components.panels.OpaquePanel; @@ -58,15 +56,8 @@ public class GroupedItemsListRenderer extends GroupedElementsRenderer.List imple @Override protected JComponent createItemComponent() { - if (Registry.is("ide.new.project.settings")) { - myTextLabel = new EngravedLabel(); - myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD)); - myTextLabel.setForeground(Gray._240); - } else { - myTextLabel = new ErrorLabel(); - myTextLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); - } - + myTextLabel = new ErrorLabel(); + myTextLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); myTextLabel.setOpaque(true); return layoutComponent(myTextLabel); } diff --git a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java new file mode 100644 index 000000000000..ac4c1b12373c --- /dev/null +++ b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java @@ -0,0 +1,465 @@ +package com.intellij.util.ui; + +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserFactory; +import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComponentWithBrowseButton; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.TextComponentAccessor; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.HyperlinkLabel; +import com.intellij.ui.TextFieldWithHistory; +import com.intellij.ui.TextFieldWithHistoryWithBrowseButton; +import com.intellij.util.NotNullProducer; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ComparatorUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class SwingHelper { + + private static final Logger LOG = Logger.getInstance(SwingHelper.class); + + /** + * Creates panel whose content consists of given {@code children} components + * stacked vertically each on another in a given order. + * + * @param childAlignmentX Component.LEFT_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.RIGHT_ALIGNMENT + * @param children children components + * @return created panel + */ + @NotNull + public static JPanel newVerticalPanel(float childAlignmentX, Component... children) { + return newGenericBoxPanel(true, childAlignmentX, children); + } + + @NotNull + public static JPanel newLeftAlignedVerticalPanel(Component... children) { + return newVerticalPanel(Component.LEFT_ALIGNMENT, children); + } + + @NotNull + public static JPanel newLeftAlignedVerticalPanel(@NotNull Collection<Component> children) { + return newVerticalPanel(Component.LEFT_ALIGNMENT, children); + } + + @NotNull + public static JPanel newVerticalPanel(float childAlignmentX, @NotNull Collection<Component> children) { + return newVerticalPanel(childAlignmentX, children.toArray(new Component[children.size()])); + } + + /** + * Creates panel whose content consists of given {@code children} components horizontally + * stacked each on another in a given order. + * + * @param childAlignmentY Component.TOP_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.BOTTOM_ALIGNMENT + * @param children children components + * @return created panel + */ + @NotNull + public static JPanel newHorizontalPanel(float childAlignmentY, Component... children) { + return newGenericBoxPanel(false, childAlignmentY, children); + } + + @NotNull + public static JPanel newHorizontalPanel(float childAlignmentY, @NotNull Collection<Component> children) { + return newHorizontalPanel(childAlignmentY, children.toArray(new Component[children.size()])); + } + + private static JPanel newGenericBoxPanel(boolean verticalOrientation, + float childAlignment, + Component... children) { + JPanel panel = new JPanel(); + int axis = verticalOrientation ? BoxLayout.Y_AXIS : BoxLayout.X_AXIS; + panel.setLayout(new BoxLayout(panel, axis)); + for (Component child : children) { + panel.add(child, childAlignment); + if (child instanceof JComponent) { + JComponent jChild = (JComponent) child; + if (verticalOrientation) { + jChild.setAlignmentX(childAlignment); + } else { + jChild.setAlignmentY(childAlignment); + } + } + } + return panel; + } + + @NotNull + public static JPanel wrapWithoutStretch(@NotNull JComponent component) { + JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + panel.add(component); + return panel; + } + + @NotNull + public static JPanel wrapWithHorizontalStretch(@NotNull JComponent component) { + JPanel panel = new JPanel(new BorderLayout(0, 0)); + panel.add(component, BorderLayout.NORTH); + return panel; + } + + public static void setPreferredWidthToFitText(@NotNull TextFieldWithHistoryWithBrowseButton component) { + int childWidth = calcWidthToFitText(component.getChildComponent().getTextEditor(), 35); + setPreferredWidthForComponentWithBrowseButton(component, childWidth); + } + + public static void setPreferredWidthToFitText(@NotNull TextFieldWithBrowseButton component) { + int childWidth = calcWidthToFitText(component.getChildComponent(), 20); + setPreferredWidthForComponentWithBrowseButton(component, childWidth); + } + + private static <T extends JComponent> void setPreferredWidthForComponentWithBrowseButton(@NotNull ComponentWithBrowseButton<T> component, + int childPrefWidth) { + Dimension buttonPrefSize = component.getButton().getPreferredSize(); + setPreferredWidth(component, childPrefWidth + buttonPrefSize.width); + } + + public static void setPreferredWidthToFitText(@NotNull JTextField textField) { + setPreferredWidthToFitText(textField, 15); + } + + public static void setPreferredWidthToFitText(@NotNull JTextField textField, int additionalWidth) { + setPreferredSizeToFitText(textField, StringUtil.notNullize(textField.getText()), additionalWidth); + } + + public static void setPreferredWidthToFitText(@NotNull JTextField textField, @NotNull String text) { + setPreferredSizeToFitText(textField, text, 15); + } + + private static void setPreferredSizeToFitText(@NotNull JTextField textField, @NotNull String text, int additionalWidth) { + int width = calcWidthToFitText(textField, text, additionalWidth); + setPreferredWidth(textField, width); + } + + private static int calcWidthToFitText(@NotNull JTextField textField, int additionalWidth) { + return calcWidthToFitText(textField, textField.getText(), additionalWidth); + } + + private static int calcWidthToFitText(@NotNull JTextField textField, @NotNull String text, int additionalWidth) { + return textField.getFontMetrics(textField.getFont()).stringWidth(text) + additionalWidth; + } + + public static void adjustDialogSizeToFitPreferredSize(@NotNull DialogWrapper dialogWrapper) { + JRootPane rootPane = dialogWrapper.getRootPane(); + Dimension componentSize = rootPane.getSize(); + Dimension componentPreferredSize = rootPane.getPreferredSize(); + if (componentPreferredSize.width <= componentSize.width && componentPreferredSize.height <= componentSize.height) { + return; + } + int dw = Math.max(0, componentPreferredSize.width - componentSize.width); + int dh = Math.max(0, componentPreferredSize.height - componentSize.height); + + Dimension oldDialogSize = dialogWrapper.getSize(); + Dimension newDialogSize = new Dimension(oldDialogSize.width + dw, oldDialogSize.height + dh); + + dialogWrapper.setSize(newDialogSize.width, newDialogSize.height); + rootPane.revalidate(); + rootPane.repaint(); + + LOG.info("DialogWrapper '" + dialogWrapper.getTitle() + "' has been resized (added width: " + dw + ", added height: " + dh + ")"); + } + + public static <T> void updateItems(@NotNull JComboBox comboBox, + @NotNull List<T> newItems, + @Nullable T newSelectedItemIfSelectionCannotBePreserved) { + if (!shouldUpdate(comboBox, newItems)) { + return; + } + Object selectedItem = comboBox.getSelectedItem(); + //noinspection SuspiciousMethodCalls + if (selectedItem != null && !newItems.contains(selectedItem)) { + selectedItem = null; + } + if (selectedItem == null && newItems.contains(newSelectedItemIfSelectionCannotBePreserved)) { + selectedItem = newSelectedItemIfSelectionCannotBePreserved; + } + comboBox.removeAllItems(); + for (T newItem : newItems) { + comboBox.addItem(newItem); + } + if (selectedItem != null) { + int count = comboBox.getItemCount(); + for (int i = 0; i < count; i++) { + Object item = comboBox.getItemAt(i); + if (selectedItem.equals(item)) { + comboBox.setSelectedIndex(i); + break; + } + } + } + } + + private static <T> boolean shouldUpdate(@NotNull JComboBox comboBox, @NotNull List<T> newItems) { + int count = comboBox.getItemCount(); + if (newItems.size() != count) { + return true; + } + for (int i = 0; i < count; i++) { + Object oldItem = comboBox.getItemAt(i); + T newItem = newItems.get(i); + if (!ComparatorUtil.equalsNullable(oldItem, newItem)) { + return true; + } + } + return false; + } + + public static void setNoBorderCellRendererFor(@NotNull TableColumn column) { + final TableCellRenderer previous = column.getCellRenderer(); + column.setCellRenderer(new DefaultTableCellRenderer() { + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + Component component; + if (previous != null) { + component = previous.getTableCellRendererComponent(table, value, isSelected, false, row, column); + } + else { + component = super.getTableCellRendererComponent(table, value, isSelected, false, row, column); + } + if (component instanceof JComponent) { + ((JComponent)component).setBorder(null); + } + return component; + } + }); + } + + public static void addHistoryOnExpansion(@NotNull final TextFieldWithHistory textFieldWithHistory, + @NotNull final NotNullProducer<List<String>> historyProvider) { + textFieldWithHistory.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + List<String> newHistory = historyProvider.produce(); + Set<String> newHistorySet = ContainerUtil.newHashSet(newHistory); + List<String> oldHistory = textFieldWithHistory.getHistory(); + List<String> mergedHistory = ContainerUtil.newArrayList(); + for (String item : oldHistory) { + if (!newHistorySet.contains(item)) { + mergedHistory.add(item); + } + } + mergedHistory.addAll(newHistory); + textFieldWithHistory.setHistory(mergedHistory); + + setLongestAsPrototype(textFieldWithHistory, mergedHistory); + + // one-time initialization + textFieldWithHistory.removePopupMenuListener(this); + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + } + + private static void setLongestAsPrototype(@NotNull JComboBox comboBox, @NotNull List<String> variants) { + Object prototypeDisplayValue = comboBox.getPrototypeDisplayValue(); + String prototypeDisplayValueStr = null; + if (prototypeDisplayValue instanceof String) { + prototypeDisplayValueStr = (String) prototypeDisplayValue; + } + else if (prototypeDisplayValue != null) { + return; + } + String longest = StringUtil.notNullize(prototypeDisplayValueStr); + boolean updated = false; + for (String s : variants) { + if (longest.length() < s.length()) { + longest = s; + updated = true; + } + } + if (updated) { + comboBox.setPrototypeDisplayValue(longest); + } + } + + public static void installFileCompletionAndBrowseDialog(@Nullable Project project, + @NotNull TextFieldWithHistoryWithBrowseButton textFieldWithHistoryWithBrowseButton, + @NotNull String browseDialogTitle, + @NotNull FileChooserDescriptor fileChooserDescriptor) { + doInstall(project, + textFieldWithHistoryWithBrowseButton, + textFieldWithHistoryWithBrowseButton.getChildComponent().getTextEditor(), + browseDialogTitle, + fileChooserDescriptor, + TextComponentAccessor.TEXT_FIELD_WITH_HISTORY_WHOLE_TEXT); + } + + public static void installFileCompletionAndBrowseDialog(@Nullable Project project, + @NotNull TextFieldWithBrowseButton textFieldWithBrowseButton, + @NotNull String browseDialogTitle, + @NotNull FileChooserDescriptor fileChooserDescriptor) { + doInstall(project, + textFieldWithBrowseButton, + textFieldWithBrowseButton.getTextField(), + browseDialogTitle, + fileChooserDescriptor, + TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT); + } + + private static <T extends JComponent> void doInstall(@Nullable Project project, + @NotNull ComponentWithBrowseButton<T> componentWithBrowseButton, + @NotNull JTextField textField, + @NotNull String browseDialogTitle, + @NotNull FileChooserDescriptor fileChooserDescriptor, + @NotNull TextComponentAccessor<T> textComponentAccessor) { + fileChooserDescriptor = fileChooserDescriptor.withShowHiddenFiles(SystemInfo.isUnix); + componentWithBrowseButton.addBrowseFolderListener( + project, + new ComponentWithBrowseButton.BrowseFolderActionListener<T>( + browseDialogTitle, + null, + componentWithBrowseButton, + project, + fileChooserDescriptor, + textComponentAccessor + ), + true + ); + FileChooserFactory.getInstance().installFileCompletion( + textField, + fileChooserDescriptor, + true, + project + ); + } + + @NotNull + public static HyperlinkLabel createWebHyperlink(@NotNull String url) { + return createWebHyperlink(url, url); + } + + @NotNull + public static HyperlinkLabel createWebHyperlink(@NotNull String text, @NotNull String url) { + HyperlinkLabel hyperlink = new HyperlinkLabel(text); + hyperlink.setHyperlinkTarget(url); + + DefaultActionGroup actionGroup = new DefaultActionGroup(); + actionGroup.add(new OpenLinkInBrowser(url)); + actionGroup.add(new CopyLinkAction(url)); + + hyperlink.setComponentPopupMenu(ActionManager.getInstance().createActionPopupMenu("web hyperlink", actionGroup).getComponent()); + return hyperlink; + } + + public static void setPreferredWidth(@NotNull JComponent component, int width) { + Dimension preferredSize = component.getPreferredSize(); + preferredSize.width = width; + component.setPreferredSize(preferredSize); + } + + @NotNull + public static JEditorPane createHtmlViewer(boolean carryTextOver, + @Nullable Font font, + @Nullable Color background, + @Nullable Color foreground) { + final JEditorPane textPane; + if (carryTextOver) { + textPane = new JEditorPane() { + @Override + public Dimension getPreferredSize() { + // This trick makes text component to carry text over to the next line + // if the text line width exceeds parent's width + Dimension dimension = super.getPreferredSize(); + dimension.width = 0; + return dimension; + } + }; + } + else { + textPane = new JEditorPane(); + } + textPane.setFont(font != null ? font : UIUtil.getLabelFont()); + textPane.setContentType(UIUtil.HTML_MIME); + textPane.setEditable(false); + textPane.setBackground(background != null ? background : UIUtil.getLabelBackground()); + textPane.setForeground(foreground != null ? foreground : UIUtil.getLabelForeground()); + return textPane; + } + + public static void setHtml(@NotNull JEditorPane editorPane, @NotNull String bodyInnerHtml) { + String html = String.format( + "<html><head>%s</head><body>%s</body></html>", + UIUtil.getCssFontDeclaration(editorPane.getFont(), null, null, null), + bodyInnerHtml + ); + editorPane.setText(html); + } + + private static class CopyLinkAction extends AnAction { + + private final String myUrl; + + private CopyLinkAction(@NotNull String url) { + super("Copy Link Address", null, PlatformIcons.COPY_ICON); + myUrl = url; + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(true); + } + + @Override + public void actionPerformed(AnActionEvent e) { + Transferable content = new StringSelection(myUrl); + CopyPasteManager.getInstance().setContents(content); + } + } + + private static class OpenLinkInBrowser extends AnAction { + + private final String myUrl; + + private OpenLinkInBrowser(@NotNull String url) { + super("Open Link in Browser", null, PlatformIcons.WEB_ICON); + myUrl = url; + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(true); + } + + @Override + public void actionPerformed(AnActionEvent e) { + BrowserUtil.browse(myUrl); + } + } +}
\ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java b/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java index dd41a33a9d15..8b148a3d791d 100644 --- a/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java +++ b/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; +import com.intellij.ui.table.JBTable; import com.intellij.ui.table.TableView; import com.intellij.util.Function; import com.intellij.util.FunctionUtil; @@ -42,6 +43,7 @@ import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; +import java.awt.*; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; @@ -71,6 +73,8 @@ public class TableModelEditor<T> implements ElementProducer<T> { table = new TableView<T>(model); table.setDefaultEditor(Enum.class, ComboBoxTableCellEditor.INSTANCE); table.setStriped(true); + table.setEnableAntialiasing(true); + preferredScrollableViewportHeightInRows(JBTable.PREFERRED_SCROLLABLE_VIEWPORT_HEIGHT_IN_ROWS); new TableSpeedSearch(table); if (columns[0].getColumnClass() == Boolean.class && columns[0].getName().isEmpty()) { TableUtil.setupCheckboxColumn(table.getColumnModel().getColumn(0)); @@ -97,6 +101,11 @@ public class TableModelEditor<T> implements ElementProducer<T> { } } + public TableModelEditor<T> preferredScrollableViewportHeightInRows(int rows) { + table.setPreferredScrollableViewportSize(new Dimension(200, table.getRowHeight() * rows)); + return this; + } + private void addDialogActions() { toolbarDecorator.setEditAction(new AnActionButtonRunnable() { @Override |