diff options
Diffstat (limited to 'platform/platform-api/src/com')
61 files changed, 1621 insertions, 1377 deletions
diff --git a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java index 939680ea372a..93a3caf6efd9 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java @@ -197,6 +197,10 @@ public class GeneralCommandLine implements UserDataHolder { * @return single-string representation of this command line. */ public String getCommandLineString(@Nullable final String exeName) { + return ParametersList.join(getCommandLineList(exeName)); + } + + public List<String> getCommandLineList(@Nullable final String exeName) { final List<String> commands = new ArrayList<String>(); if (exeName != null) { commands.add(exeName); @@ -208,7 +212,7 @@ public class GeneralCommandLine implements UserDataHolder { commands.add("<null>"); } commands.addAll(myProgramParams.getList()); - return ParametersList.join(commands); + return commands; } /** @@ -224,6 +228,7 @@ public class GeneralCommandLine implements UserDataHolder { return StringUtil.join(CommandLineUtil.toCommandLine(exePath, myProgramParams.getList(), platform), "\n"); } + @NotNull public Process createProcess() throws ExecutionException { if (LOG.isDebugEnabled()) { LOG.debug("Executing [" + getCommandLineString() + "]"); @@ -253,6 +258,7 @@ public class GeneralCommandLine implements UserDataHolder { } } + @NotNull protected Process startProcess(@NotNull List<String> commands) throws IOException { ProcessBuilder builder = new ProcessBuilder(commands); setupEnvironment(builder.environment()); diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java index 7e879f496c1b..bab90cfcd9b5 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/PathEnvironmentVariableUtil.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.FileFilter; import java.util.Collections; import java.util.List; @@ -51,6 +52,19 @@ public class PathEnvironmentVariableUtil { /** * Finds an executable file with the specified base name, that is located in a directory + * listed in PATH environment variable and is accepted by filter. + * + * @param fileBaseName file base name + * @param filter exe file filter + * @return {@code File} instance or null if not found + */ + @Nullable + public static File findInPath(@NotNull String fileBaseName, @Nullable FileFilter filter) { + return findInPath(fileBaseName, false, filter); + } + + /** + * Finds an executable file with the specified base name, that is located in a directory * listed in PATH environment variable. * * @param fileBaseName file base name @@ -59,7 +73,12 @@ public class PathEnvironmentVariableUtil { */ @Nullable public static File findInPath(@NotNull String fileBaseName, boolean logDetails) { - List<File> exeFiles = findExeFilesInPath(fileBaseName, true, logDetails); + return findInPath(fileBaseName, logDetails, null); + } + + @Nullable + private static File findInPath(@NotNull String fileBaseName, boolean logDetails, @Nullable FileFilter filter) { + List<File> exeFiles = findExeFilesInPath(fileBaseName, true, logDetails, filter); return exeFiles.size() > 0 ? exeFiles.get(0) : null; } @@ -79,7 +98,7 @@ public class PathEnvironmentVariableUtil { else { originalPath = EnvironmentUtil.getValue(PATH_ENV_VAR_NAME); } - List<File> exeFiles = doFindExeFilesInPath(originalPath, fileBaseName, true, false); + List<File> exeFiles = doFindExeFilesInPath(originalPath, fileBaseName, true, false, null); return exeFiles.size() > 0 ? exeFiles.get(0) : null; } @@ -92,22 +111,29 @@ public class PathEnvironmentVariableUtil { */ @NotNull public static List<File> findAllExeFilesInPath(@NotNull String fileBaseName) { - return findExeFilesInPath(fileBaseName, false, false); + return findAllExeFilesInPath(fileBaseName, null); + } + + @NotNull + public static List<File> findAllExeFilesInPath(@NotNull String fileBaseName, @Nullable FileFilter filter) { + return findExeFilesInPath(fileBaseName, false, false, filter); } @NotNull private static List<File> findExeFilesInPath(@NotNull String fileBaseName, boolean stopAfterFirstMatch, - boolean logDetails) { + boolean logDetails, + @Nullable FileFilter filter) { String systemPath = EnvironmentUtil.getValue(PATH_ENV_VAR_NAME); - return doFindExeFilesInPath(systemPath, fileBaseName, stopAfterFirstMatch, logDetails); + return doFindExeFilesInPath(systemPath, fileBaseName, stopAfterFirstMatch, logDetails, filter); } @NotNull private static List<File> doFindExeFilesInPath(@Nullable String pathEnvVarValue, @NotNull String fileBaseName, boolean stopAfterFirstMatch, - boolean logDetails) { + boolean logDetails, + @Nullable FileFilter filter) { if (logDetails) { LOG.info("Finding files in PATH (base name=" + fileBaseName + ", PATH=" + StringUtil.notNullize(pathEnvVarValue) + ")."); } @@ -124,11 +150,13 @@ public class PathEnvironmentVariableUtil { + ", file.isFile:" + file.isFile() + ", file.canExecute:" + file.canExecute()); } if (dir.isAbsolute() && dir.isDirectory()) { - File file = new File(dir, fileBaseName); - if (file.isFile() && file.canExecute()) { - result.add(file); - if (stopAfterFirstMatch) { - return result; + File exeFile = new File(dir, fileBaseName); + if (exeFile.isFile() && exeFile.canExecute()) { + if (filter == null || filter.accept(exeFile)) { + result.add(exeFile); + if (stopAfterFirstMatch) { + return result; + } } } } diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java index 5e3d74caa1f6..182d347de4c1 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java @@ -37,6 +37,7 @@ public class PtyCommandLine extends GeneralCommandLine { public PtyCommandLine() { } + @NotNull @Override protected Process startProcess(@NotNull List<String> commands) throws IOException { if (SystemInfo.isUnix) { diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java index 58a8e40db2d6..67c4af413e74 100644 --- a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java +++ b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java @@ -17,6 +17,7 @@ package com.intellij.execution.process; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,11 +60,13 @@ public class AnsiEscapeDecoder { if (escSeqEndInd < 0) { break; } - String escSeq = text.substring(escSeqBeginInd, escSeqEndInd); - // this is a simple fix for RUBY-8996: - // we replace several consecutive escape sequences with one which contains all these sequences - String colorAttribute = INNER_PATTERN.matcher(escSeq).replaceAll(";"); - myCurrentTextAttributes = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute); + if (text.charAt(escSeqEndInd - 1) == 'm') { + String escSeq = text.substring(escSeqBeginInd, escSeqEndInd); + // this is a simple fix for RUBY-8996: + // we replace several consecutive escape sequences with one which contains all these sequences + String colorAttribute = INNER_PATTERN.matcher(escSeq).replaceAll(";"); + myCurrentTextAttributes = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute); + } pos = escSeqEndInd; } if (pos < text.length()) { @@ -78,16 +81,41 @@ public class AnsiEscapeDecoder { * Selects all consecutive escape sequences and returns escape sequence end index (exclusive). * If the escape sequence isn't finished, returns -1. */ - private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) { - escSeqBeginInd = text.indexOf('m', escSeqBeginInd); - while (escSeqBeginInd >= 0) { - escSeqBeginInd++; - if (!text.regionMatches(escSeqBeginInd, CSI, 0, CSI.length())) { + private static int findEscSeqEndIndex(@NotNull String text, final int escSeqBeginInd) { + int beginInd = escSeqBeginInd; + while (true) { + int letterInd = findEscSeqLetterIndex(text, beginInd); + if (letterInd == -1) { + return beginInd == escSeqBeginInd ? -1 : beginInd; + } + if (text.charAt(letterInd) != 'm') { + return beginInd == escSeqBeginInd ? letterInd + 1 : beginInd; + } + beginInd = letterInd + 1; + } + } + + private static int findEscSeqLetterIndex(@NotNull String text, int escSeqBeginInd) { + if (!text.regionMatches(escSeqBeginInd, CSI, 0, CSI.length())) { + return -1; + } + int parameterEndInd = escSeqBeginInd + 2; + while (parameterEndInd < text.length()) { + char ch = text.charAt(parameterEndInd); + if (Character.isDigit(ch) || ch == ';') { + parameterEndInd++; + } + else { break; } - escSeqBeginInd = text.indexOf('m', escSeqBeginInd); } - return escSeqBeginInd; + if (parameterEndInd < text.length()) { + char letter = text.charAt(parameterEndInd); + if (StringUtil.containsChar("ABCDEFGHJKSTfmisu", letter)) { + return parameterEndInd; + } + } + return -1; } @Nullable diff --git a/platform/platform-api/src/com/intellij/ide/UiActivity.java b/platform/platform-api/src/com/intellij/ide/UiActivity.java index 9066837fb0a8..49fcd1a74ada 100644 --- a/platform/platform-api/src/com/intellij/ide/UiActivity.java +++ b/platform/platform-api/src/com/intellij/ide/UiActivity.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. @@ -26,13 +26,13 @@ import java.util.List; public class UiActivity implements ComparableObject{ - private List<String> myElements = new ArrayList<String>(); + private final List<String> myElements = new ArrayList<String>(); - public UiActivity(String ... elements) { + public UiActivity(@NotNull String ... elements) { this(elements, null); } - protected UiActivity(String[] elements1, @Nullable String[] elements2) { + protected UiActivity(@NotNull String[] elements1, @Nullable String[] elements2) { myElements.addAll(Arrays.asList(elements1)); if (elements2 != null) { myElements.addAll(Arrays.asList(elements2)); diff --git a/platform/platform-api/src/com/intellij/ide/UiActivityMonitor.java b/platform/platform-api/src/com/intellij/ide/UiActivityMonitor.java index 8591383dc6d5..3ecb5727cc30 100644 --- a/platform/platform-api/src/com/intellij/ide/UiActivityMonitor.java +++ b/platform/platform-api/src/com/intellij/ide/UiActivityMonitor.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. @@ -22,10 +22,11 @@ import com.intellij.openapi.util.BusyObject; import org.jetbrains.annotations.NotNull; public abstract class UiActivityMonitor { + @NotNull + public abstract BusyObject getBusy(@NotNull Project project, @NotNull UiActivity ... toWatch); - public abstract BusyObject getBusy(@NotNull Project project, UiActivity ... toWatch); - - public abstract BusyObject getBusy(UiActivity ... toWatch); + @NotNull + public abstract BusyObject getBusy(@NotNull UiActivity ... toWatch); public abstract void addActivity(@NotNull Project project, @NotNull UiActivity activity); diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java index 736dcd8afe22..c5843b3d53c8 100644 --- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java +++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java @@ -127,6 +127,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { GeneralSettings settings = getGeneralSettingsInstance(); if (settings.isUseDefaultBrowser()) { + boolean tryToUseCli = true; if (isDesktopActionSupported(Desktop.Action.BROWSE)) { try { Desktop.getDesktop().browse(uri); @@ -135,13 +136,17 @@ public class BrowserLauncherAppless extends BrowserLauncher { } catch (Exception e) { LOG.warn("Error while using Desktop API, fallback to CLI", e); + // if "No application knows how to open", then we must not try to use OS open + tryToUseCli = !e.getMessage().contains("Error code: -10814"); } } - List<String> command = getDefaultBrowserCommand(); - if (command != null) { - doLaunch(uri.toString(), command, null, project, ArrayUtil.EMPTY_STRING_ARRAY, null); - return; + if (tryToUseCli) { + List<String> command = getDefaultBrowserCommand(); + if (command != null) { + doLaunch(uri.toString(), command, null, project, ArrayUtil.EMPTY_STRING_ARRAY, null); + return; + } } } @@ -171,7 +176,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { File file = new File(url); if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) { if (!file.exists()) { - doShowError(IdeBundle.message("error.file.does.not.exist", file.getPath()), null, null, null, null); + showError(IdeBundle.message("error.file.does.not.exist", file.getPath()), null, null, null, null); return; } @@ -189,10 +194,10 @@ public class BrowserLauncherAppless extends BrowserLauncher { } if (uri == null) { - doShowError(IdeBundle.message("error.malformed.url", url), null, project, null, null); + showError(IdeBundle.message("error.malformed.url", url), null, project, null, null); } else { - browse(uri); + browse(uri, project); } } @@ -438,7 +443,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { String message = browser != null ? browser.getBrowserNotFoundMessage() : IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()); - doShowError(message, browser, project, IdeBundle.message("title.browser.not.found"), launchTask); + showError(message, browser, project, IdeBundle.message("title.browser.not.found"), launchTask); return false; } @@ -475,7 +480,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { return true; } catch (ExecutionException e) { - doShowError(e.getMessage(), browser, project, null, null); + showError(e.getMessage(), browser, project, null, null); return false; } } @@ -487,7 +492,7 @@ public class BrowserLauncherAppless extends BrowserLauncher { @Nullable Runnable launchTask) { } - protected void doShowError(@Nullable String error, @Nullable WebBrowser browser, @Nullable Project project, String title, @Nullable Runnable launchTask) { + protected void showError(@Nullable String error, @Nullable WebBrowser browser, @Nullable Project project, String title, @Nullable Runnable launchTask) { // Not started yet. Not able to show message up. (Could happen in License panel under Linux). LOG.warn(error); } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 202483d0117b..10285d05fbee 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -83,7 +83,7 @@ public class AbstractTreeUi { } }; long myOwnComparatorStamp; - long myLastComparatorStamp; + private long myLastComparatorStamp; private DefaultMutableTreeNode myRootNode; private final Map<Object, Object> myElementToNodeMap = new HashMap<Object, Object>(); @@ -109,7 +109,7 @@ public class AbstractTreeUi { private final Map<Object, List<NodeAction>> myNodeChildrenActions = new HashMap<Object, List<NodeAction>>(); private long myClearOnHideDelay = -1; - private final Map<AbstractTreeUi, Long> ourUi2Countdown = Collections.synchronizedMap(new WeakHashMap<AbstractTreeUi, Long>()); + private volatile long ourUi2Countdown; private final Set<Runnable> myDeferredSelections = new HashSet<Runnable>(); private final Set<Runnable> myDeferredExpansions = new HashSet<Runnable>(); @@ -263,7 +263,7 @@ public class AbstractTreeUi { } - boolean isNodeActionsPending() { + private boolean isNodeActionsPending() { return !myNodeActions.isEmpty() || !myNodeChildrenActions.isEmpty(); } @@ -310,28 +310,23 @@ public class AbstractTreeUi { private void cleanUpAll() { final long now = System.currentTimeMillis(); - final AbstractTreeUi[] uis = ourUi2Countdown.keySet().toArray(new AbstractTreeUi[ourUi2Countdown.size()]); - for (AbstractTreeUi eachUi : uis) { - if (eachUi == null) continue; - final Long timeToCleanup = ourUi2Countdown.get(eachUi); - if (timeToCleanup == null) continue; - if (now >= timeToCleanup.longValue()) { - ourUi2Countdown.remove(eachUi); - Runnable runnable = new Runnable() { - @Override - public void run() { - if (!canInitiateNewActivity()) return; + final long timeToCleanup = ourUi2Countdown; + if (timeToCleanup != 0 && now >= timeToCleanup) { + ourUi2Countdown = 0; + Runnable runnable = new Runnable() { + @Override + public void run() { + if (!canInitiateNewActivity()) return; - myCleanupTask = null; - getBuilder().cleanUp(); - } - }; - if (isPassthroughMode()) { - runnable.run(); - } - else { - invokeLaterIfNeeded(false, runnable); + myCleanupTask = null; + getBuilder().cleanUp(); } + }; + if (isPassthroughMode()) { + runnable.run(); + } + else { + invokeLaterIfNeeded(false, runnable); } } } @@ -390,7 +385,7 @@ public class AbstractTreeUi { cancelCurrentCleanupTask(); myCanProcessDeferredSelections = true; - ourUi2Countdown.remove(this); + ourUi2Countdown = 0; if (!myWasEverShown || myUpdateFromRootRequested || myUpdateIfInactive) { getBuilder().updateFromRoot(); @@ -408,7 +403,7 @@ public class AbstractTreeUi { } } - public void deactivate() { + void deactivate() { getUpdater().hideNotify(); myBusyAlarm.cancelAllRequests(); @@ -420,7 +415,7 @@ public class AbstractTreeUi { } if (getClearOnHideDelay() >= 0) { - ourUi2Countdown.put(this, System.currentTimeMillis() + getClearOnHideDelay()); + ourUi2Countdown = System.currentTimeMillis() + getClearOnHideDelay(); scheduleCleanUpAll(); } } @@ -687,7 +682,7 @@ public class AbstractTreeUi { wasCleanedUp = true; } - if (myRootNodeWasQueuedToInitialize) return wasCleanedUp; + if (myRootNodeWasQueuedToInitialize) return true; myRootNodeWasQueuedToInitialize = true; @@ -2878,7 +2873,7 @@ public class AbstractTreeUi { if (!getBuilder().isSmartExpand()) return false; boolean smartExpand = !myNotForSmartExpand.contains(node) && canSmartExpand; - return smartExpand && validateAutoExpand(smartExpand, getElementFor(node)); + return smartExpand && validateAutoExpand(true, getElementFor(node)); } private void processSmartExpand(@NotNull final DefaultMutableTreeNode node, final boolean canSmartExpand, boolean forced) { @@ -3778,7 +3773,7 @@ public class AbstractTreeUi { final boolean oldCanProcessDeferredSelection = myCanProcessDeferredSelections; - if (!deferred && wasRootNodeInitialized() && willAffectSelection) { + if (!deferred && wasRootNodeInitialized()) { _getReady().doWhenDone(new Runnable() { @Override public void run() { @@ -4357,12 +4352,13 @@ public class AbstractTreeUi { Object eachElement = element; DefaultMutableTreeNode firstVisible = null; while (true) { - if (!isValid(eachElement) || eachElement == null) break; + if (eachElement == null || !isValid(eachElement)) break; final int preselected = getRowIfUnderSelection(eachElement); if (preselected >= 0) { firstVisible = (DefaultMutableTreeNode)getTree().getPathForRow(preselected).getLastPathComponent(); - } else { + } + else { firstVisible = getNodeForElement(eachElement, true); } @@ -4371,15 +4367,20 @@ public class AbstractTreeUi { kidsToExpand.add(eachElement); } if (firstVisible != null) break; - eachElement = eachElement != null ? getTreeStructure().getParentElement(eachElement) : null; + eachElement = getTreeStructure().getParentElement(eachElement); if (eachElement == null) { firstVisible = null; break; } - if (kidsToExpand.contains(eachElement)) { + int i = kidsToExpand.indexOf(eachElement); + if (i != -1) { try { - LOG.error("Tree path contains equal elements at different levels: element=" + eachElement + " class=" + eachElement.getClass() + " path=" + kidsToExpand + " tree structure=" + myTreeStructure); + Object existing = kidsToExpand.get(i); + LOG.error("Tree path contains equal elements at different levels:\n" + + " element: '" + eachElement + "'; " + eachElement.getClass() + " ("+System.identityHashCode(eachElement)+");\n" + + "existing: '" + existing + "'; " + existing.getClass()+ " ("+System.identityHashCode(existing)+"); " + + "path='" + kidsToExpand + "'; tree structure=" + myTreeStructure); } catch (AssertionError ignored) { } @@ -5044,6 +5045,7 @@ public class AbstractTreeUi { return myUpdateChildren; } + @Override @NotNull @NonNls public synchronized String toString() { diff --git a/platform/platform-api/src/com/intellij/mock/MockProgressIndicator.java b/platform/platform-api/src/com/intellij/mock/MockProgressIndicator.java index f69cf9b0b963..bc2fd80a5efa 100644 --- a/platform/platform-api/src/com/intellij/mock/MockProgressIndicator.java +++ b/platform/platform-api/src/com/intellij/mock/MockProgressIndicator.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. @@ -15,97 +15,11 @@ */ package com.intellij.mock; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.progress.ProgressIndicator; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.progress.EmptyProgressIndicator; +import org.jetbrains.annotations.TestOnly; -public class MockProgressIndicator implements ProgressIndicator { - private boolean myIsRunning = false; - private boolean myIsCanceled = false; - - public void start() { - myIsRunning = true; - myIsCanceled = false; - } - - public void stop() { - myIsRunning = false; - } - - public boolean isRunning() { - return myIsRunning; - } - - public void cancel() { - myIsCanceled = true; - } - - public boolean isCanceled() { - return myIsCanceled; - } - - public void setText(String text) { - } - - public String getText() { - return ""; - } - - public void setText2(String text) { - } - - public String getText2() { - return ""; - } - - public double getFraction() { - return 1; - } - - public void setFraction(double fraction) { - } - - public void pushState() { - } - - public void popState() { - } - - public void startNonCancelableSection() { - } - - public void finishNonCancelableSection() { - } - - public boolean isModal() { - return false; - } - - @NotNull - public ModalityState getModalityState() { - return ModalityState.NON_MODAL; - } - - public void setModalityProgress(ProgressIndicator modalityProgress) { - } - - public boolean isIndeterminate() { - return false; - } - - public void setIndeterminate(boolean indeterminate) { - } - - public void checkCanceled() { - } - - @Override - public boolean isPopupWasShown() { - return false; - } - - @Override - public boolean isShowing() { - return false; +public class MockProgressIndicator extends EmptyProgressIndicator { + @TestOnly + public MockProgressIndicator() { } } diff --git a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java index 7285a8e1ffd6..df68daff1584 100644 --- a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java +++ b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java @@ -66,6 +66,10 @@ public final class NotificationGroup { return new NotificationGroup(displayId, NotificationDisplayType.TOOL_WINDOW, logByDefault, toolWindowId); } + public static NotificationGroup toolWindowGroup(@NotNull String displayId, @NotNull String toolWindowId) { + return toolWindowGroup(displayId, toolWindowId, true); + } + public String getDisplayId() { return myDisplayId; } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java index e3248b863aba..16a81d2218d2 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java @@ -76,6 +76,7 @@ public abstract class ActionPlaces { public static final String ANT_MESSAGES_TOOLBAR = "AntMessagesToolbar"; public static final String ANT_EXPLORER_POPUP = "AntExplorerPopup"; public static final String ANT_EXPLORER_TOOLBAR = "AntExplorerToolbar"; + public static final String GULP_VIEW_POPUP = "JavaScriptGulpPopup"; //todo: probably these context should be splitted into several contexts public static final String CODE_INSPECTION = "CodeInspection"; @@ -133,7 +134,7 @@ public abstract class ActionPlaces { FILEVIEW_POPUP, CHECKOUT_POPUP, LVCS_DIRECTORY_HISTORY_POPUP, GUI_DESIGNER_EDITOR_POPUP, GUI_DESIGNER_COMPONENT_TREE_POPUP, GUI_DESIGNER_PROPERTY_INSPECTOR_POPUP, CREATE_EJB_POPUP, CHANGES_VIEW_POPUP, REMOTE_HOST_VIEW_POPUP, REMOTE_HOST_DIALOG_POPUP, TFS_TREE_POPUP, - ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION, PHING_EXPLORER_POPUP, NAVIGATION_BAR_POPUP + ACTION_PLACE_VCS_QUICK_LIST_POPUP_ACTION, PHING_EXPLORER_POPUP, NAVIGATION_BAR_POPUP, GULP_VIEW_POPUP }; public static boolean isPopupPlace(@NotNull String place) { diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionStub.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionStub.java index 09896aaf0da8..c96ce2aa3371 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionStub.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionStub.java @@ -29,6 +29,7 @@ public class ActionStub extends AnAction{ private static final Logger LOG=Logger.getInstance("#com.intellij.openapi.actionSystem.ActionStub"); private final String myClassName; + private final String myProjectType; private final String myId; private final String myText; private final ClassLoader myLoader; @@ -40,9 +41,10 @@ public class ActionStub extends AnAction{ @NotNull String text, ClassLoader loader, PluginId pluginId, - String iconPath) { + String iconPath, String projectType) { myLoader = loader; myClassName=actionClass; + myProjectType = projectType; LOG.assertTrue(!id.isEmpty()); myId=id; myText=text; @@ -102,4 +104,7 @@ public class ActionStub extends AnAction{ targetAction.setShortcutSet(getShortcutSet()); } + public String getProjectType() { + return myProjectType; + } } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java index 994dd130c384..a1441565d90b 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java @@ -15,9 +15,11 @@ */ package com.intellij.openapi.actionSystem; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.InputEvent; @@ -148,9 +150,13 @@ public class CommonShortcuts { return shortcutsById(IdeActions.ACTION_DELETE); } + @NotNull private static CustomShortcutSet shortcutsById(String actionId) { - if (ApplicationManager.getApplication() == null) return new CustomShortcutSet(Shortcut.EMPTY_ARRAY); - - return new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts(actionId)); + Application application = ApplicationManager.getApplication(); + KeymapManager keymapManager = application == null ? null : application.getComponent(KeymapManager.class); + if (keymapManager == null) { + return new CustomShortcutSet(Shortcut.EMPTY_ARRAY); + } + return new CustomShortcutSet(keymapManager.getActiveKeymap().getShortcuts(actionId)); } } diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java index cd0dd2aef263..ffacf59315cd 100644 --- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java +++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ import com.intellij.openapi.extensions.ExtensionPointName; import org.jetbrains.annotations.NonNls; /** - * Implementors of this interface declared via {@link com.intellij.ExtensionPoints#APPLICATION_STARTER} contribute a - * command line application based on IDEA platform. + * Implementers of the interface declared via {@link com.intellij.ExtensionPoints#APPLICATION_STARTER} + * contribute to a command-line processing capability of an application. * * @author max * @see ApplicationStarterEx @@ -30,25 +30,26 @@ public interface ApplicationStarter { ExtensionPointName<ApplicationStarter> EP_NAME = ExtensionPointName.create(ExtensionPoints.APPLICATION_STARTER); /** - * Command line switch to start with this runner. For example return "inspect" if you'd like to start app with - * <code>idea.exe inspect</code> cmdline. - * @return command line selector. + * Command-line switch to start with this runner. + * For example return {@code "inspect"} if you'd like to start an app with {@code "idea.exe inspect ..."} command). + * + * @return command-line selector. */ @NonNls String getCommandName(); /** - * Called before application initialization. Invoked in awt dispatch thread. - * @param args cmdline arguments including declared selector. For example <code>"idea.exe inspect myproject.ipr"</code> - * will pass <code>{"inspect", "myproject.ipr"}</code> + * Called before application initialization. Invoked in event dispatch thread. + * + * @param args program arguments (including the selector) */ void premain(String[] args); /** - * Called when application have been initialized. Invoked in awt dispatch thread. An application starter should take care terminating - * JVM itself when appropriate by calling {@link java.lang.System#exit}(0); - * @param args cmdline arguments including declared selector. For example <code>"idea.exe inspect myproject.ipr"</code> - * will pass <code>{"inspect", "myproject.ipr"}</code> + * <p>Called when application has been initialized. Invoked in event dispatch thread.</p> + * <p>An application starter should take care of terminating JVM when appropriate by calling {@link System#exit}.</p> + * + * @param args program arguments (including the selector) */ void main(String[] args); } diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java index f84fc1481547..c4b3a6384f56 100644 --- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java +++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.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,11 +16,17 @@ package com.intellij.openapi.application; /** - * Implementors of this interface declared via {@link com.intellij.ExtensionPoints#APPLICATION_STARTER} are also capable of processing - * an external command line within a running IntelliJ Platform instance. - + * Implementers of the interface declared via {@link com.intellij.ExtensionPoints#APPLICATION_STARTER} + * may be capable of processing an external command line within a running IntelliJ Platform instance. + * * @author yole */ -public interface ApplicationStarterEx extends ApplicationStarter { - void processExternalCommandLine(String[] args); +public abstract class ApplicationStarterEx implements ApplicationStarter { + public abstract boolean isHeadless(); + + public boolean canProcessExternalCommandLine() { + return false; + } + + public void processExternalCommandLine(String[] args) { } } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java b/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java index a8dbcdbc45e0..c4ae87fb1e02 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java @@ -29,7 +29,7 @@ public abstract class ActionButtonPresentation { } }; - public static ActionButtonPresentation CANCEL_WITH_PROMPT = new ActionButtonPresentation(CommonBundle.getCancelButtonText()) { + public static ActionButtonPresentation CANCEL_WITH_PROMPT = new ActionButtonPresentation("Revert") { @Override public void run(DialogWrapper dialog) { if (Messages.showYesNoDialog(dialog.getRootPane(), diff --git a/platform/platform-api/src/com/intellij/openapi/diff/ApplicationStarterBase.java b/platform/platform-api/src/com/intellij/openapi/diff/ApplicationStarterBase.java deleted file mode 100644 index 21e9f7595082..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/diff/ApplicationStarterBase.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.diff; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ApplicationStarterEx; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.io.StreamUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Arrays; - -/** - * @author Konstantin Bulenkov - */ -@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"}) -public abstract class ApplicationStarterBase implements ApplicationStarterEx { - private final String myCommandName; - private final int[] myArgsCount; - - protected ApplicationStarterBase(String commandName, int... possibleArgumentsCount) { - myCommandName = commandName; - myArgsCount = possibleArgumentsCount; - } - - @Override - public String getCommandName() { - return myCommandName; - } - - @Override - public void processExternalCommandLine(String[] args) { - if (!checkArguments(args)) { - Messages.showMessageDialog(getUsageMessage(), StringUtil.toTitleCase(getCommandName()), Messages.getInformationIcon()); - return; - } - try { - processCommand(args); - } - catch (Exception e) { - Messages.showMessageDialog(String.format("Error showing %s: %s", getCommandName(), e.getMessage()), - StringUtil.toTitleCase(getCommandName()), - Messages.getErrorIcon()); - } - finally { - saveAll(); - } - } - - private static void saveAll() { - FileDocumentManager.getInstance().saveAllDocuments(); - ApplicationManager.getApplication().saveSettings(); - } - - private boolean checkArguments(String[] args) { - return Arrays.binarySearch(myArgsCount, args.length - 1) != -1 && getCommandName().equals(args[0]); - } - - public abstract String getUsageMessage(); - - protected abstract void processCommand(String[] args) throws Exception; - - @Override - public void premain(String[] args) { - if (!checkArguments(args)) { - System.err.println(getUsageMessage()); - System.exit(1); - } - } - - @Override - public void main(String[] args) { - try { - processCommand(args); - } - catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - catch (Throwable t) { - t.printStackTrace(); - System.exit(2); - } - finally { - saveAll(); - } - - System.exit(0); - } - - public static VirtualFile findOrCreateFile(String path) throws IOException { - final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path)); - if (file == null) { - boolean result = new File(path).createNewFile(); - if (result) { - return findFile(path); - } - else { - throw new FileNotFoundException("Can't create file " + path); - } - } - return file; - } - - /** - * Get direct from file because IDEA cache files(see #IDEA-81067) - */ - public static String getText(VirtualFile file) throws IOException { - FileInputStream inputStream = new FileInputStream(file.getPath()); - try { - return StreamUtil.readText(inputStream); - } - finally { - inputStream.close(); - } - } - - public static boolean haveDirs(VirtualFile... files) { - for (VirtualFile file : files) { - if (file.isDirectory()) { - return true; - } - } - return false; - } - - public static boolean areJars(VirtualFile file1, VirtualFile file2) { - return JarFileSystem.PROTOCOL.equalsIgnoreCase(file1.getExtension()) && JarFileSystem.PROTOCOL.equalsIgnoreCase(file2.getExtension()); - } - - public static boolean areDirs(VirtualFile file1, VirtualFile file2) { - return file1.isDirectory() && file2.isDirectory(); - } - - public static class OperationFailedException extends IOException { - public OperationFailedException(@NotNull String message) { - super(message); - } - } - - @NotNull - public static VirtualFile findFile(final String path) throws OperationFailedException { - File ioFile = new File(path); - if (!ioFile.exists()) { - final String dir = PathManager.getOriginalWorkingDir(); - ioFile = new File(dir + File.separator + path); - } - final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile); - if (file == null) { - throw new OperationFailedException("Can't find file " + path); - } - return file; - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java deleted file mode 100644 index ceb075a17095..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffApplication.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.diff; - -import com.intellij.ide.diff.DiffElement; -import com.intellij.ide.diff.DirDiffSettings; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.fileTypes.UnknownFileType; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.vfs.VirtualFile; - -/** - * @author max - * @author Konstantin Bulenkov - */ -@SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace"}) -public class DiffApplication extends ApplicationStarterBase { - public DiffApplication() { - super("diff", 2); - } - - public String getUsageMessage() { - final String scriptName = ApplicationNamesInfo.getInstance().getScriptName(); - return DiffBundle.message("diff.application.usage.parameters.and.description", scriptName); - } - - public void processCommand(String[] args) throws OperationFailedException { - final String path1 = args[1]; - final String path2 = args[2]; - final VirtualFile file1 = findFile(path1); - final VirtualFile file2 = findFile(path2); - final boolean areDirs = areDirs(file1, file2); - final boolean areJars = areJars(file1, file2); - if (areDirs || areJars) { - final DirDiffManager diffManager = DirDiffManager.getInstance(ProjectManager.getInstance().getDefaultProject()); - final DiffElement d1 = diffManager.createDiffElement(file1); - final DiffElement d2 = diffManager.createDiffElement(file2); - if (d1 == null) { - throw new OperationFailedException(DiffBundle.message("cannot.create.diff.error", path1)); - } - if (d2 == null) { - throw new OperationFailedException(DiffBundle.message("cannot.create.diff.error", path1)); - } - else if (!diffManager.canShow(d1, d2)) { - throw new OperationFailedException(DiffBundle.message("cannot.compare.error", path1, path2)); - } - - final DirDiffSettings settings = new DirDiffSettings(); - settings.showInFrame = false; - diffManager.showDiff(d1, d2, settings, null); - } - else { - file1.refresh(false, false); - file2.refresh(false, false); - - if (file1.getFileType() == UnknownFileType.INSTANCE) { - throw new OperationFailedException(DiffBundle.message("unknown.file.type.error", path1)); - } - else if (file2.getFileType() == UnknownFileType.INSTANCE) { - throw new OperationFailedException(DiffBundle.message("unknown.file.type.error", path2)); - } - - SimpleDiffRequest request = SimpleDiffRequest.compareFiles(file1, file2, ProjectManager.getInstance().getDefaultProject()); - request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); - DiffManager.getInstance().getIdeaDiffTool().show(request); - } - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java deleted file mode 100644 index b2e29f1bc88d..000000000000 --- a/platform/platform-api/src/com/intellij/openapi/diff/MergeApplication.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.diff; - -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.vfs.VirtualFile; - -/** - * @author Konstantin Bulenkov - */ -public class MergeApplication extends ApplicationStarterBase { - public MergeApplication() { - super("merge", 3 ,4); - } - - @Override - public String getUsageMessage() { - final String script = ApplicationNamesInfo.getInstance().getScriptName(); - return String.format("Usage:\n\t%s merge <file1> <file2> <original>\n\t%s merge <file1> <file2> <original> <output>", script, script); - } - - @Override - protected void processCommand(String[] args) throws Exception { - final VirtualFile left = findFile(args[1]); - final VirtualFile right = findFile(args[2]); - final VirtualFile middle = findFile(args[3]); - final VirtualFile result = findOrCreateFile(args.length == 4 ? args[3] : args[4]); - - MergeRequest request = DiffRequestFactory.getInstance() - .createMergeRequest(getText(left), getText(right), getText(middle), result, - ProjectManager.getInstance().getDefaultProject(), - ActionButtonPresentation.APPLY, - ActionButtonPresentation.CANCEL_WITH_PROMPT); - request.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG); - request.setWindowTitle("Merge"); - request.setVersionTitles(new String[]{left.getPresentableUrl(), result.getPresentableUrl(), middle.getPresentableUrl()}); - DiffManager.getInstance().getDiffTool().show(request); - } -} diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java index c19173c7e906..7509394a2368 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptor.java @@ -18,6 +18,7 @@ package com.intellij.openapi.fileChooser; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VFileProperty; @@ -51,6 +52,7 @@ public class FileChooserDescriptor implements Cloneable { private boolean myShowFileSystemRoots = true; private boolean myTreeRootVisible = false; private boolean myShowHiddenFiles = false; + private Condition<VirtualFile> myFileFilter = null; private final Map<String, Object> myUserData = new HashMap<String, Object>(); @@ -218,18 +220,15 @@ public class FileChooserDescriptor implements Cloneable { } /** - * Defines whether file can be chosen or not + * Sets simple boolean condition for use in {@link #isFileVisible(VirtualFile, boolean)} and {@link #isFileSelectable(VirtualFile)}. */ - public boolean isFileSelectable(VirtualFile file) { - if (file == null) return false; - if (file.isDirectory() && myChooseFolders) return true; - if (acceptAsJarFile(file)) return true; - if (acceptAsGeneralFile(file)) return true; - return false; + public FileChooserDescriptor withFileFilter(@Nullable Condition<VirtualFile> filter) { + myFileFilter = filter; + return this; } /** - * Defines whether file is visible in the tree + * Defines whether a file is visible in the tree. */ public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { if (!file.isDirectory()) { @@ -238,28 +237,47 @@ public class FileChooserDescriptor implements Cloneable { return false; } } - else { - if (!myChooseFiles) { - return false; - } + else if (!myChooseFiles) { + return false; + } + if (myFileFilter != null && !myFileFilter.value(file)) { + return false; } } - // do not include ignored files if (isHideIgnored() && FileTypeManager.getInstance().isFileIgnored(file)) { return false; } - // do not include hidden files - if (!showHiddenFiles) { - if (FileElement.isFileHidden(file)) { - return false; - } + if (!showHiddenFiles && FileElement.isFileHidden(file)) { + return false; } return true; } + /** + * Defines whether a file can be chosen. + */ + public boolean isFileSelectable(VirtualFile file) { + if (file == null) return false; + + if (file.isDirectory() && myChooseFolders) { + return true; + } + if (acceptAsJarFile(file)) { + return true; + } + if (acceptAsGeneralFile(file)) { + return true; + } + if (myFileFilter != null && !file.isDirectory() && myFileFilter.value(file)) { + return true; + } + + return false; + } + public Icon getIcon(final VirtualFile file) { if (file.isDirectory()) { return dressIcon(file, PlatformIcons.DIRECTORY_CLOSED_ICON); diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java index c958dbca878e..2eee60aa3061 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java @@ -16,14 +16,13 @@ package com.intellij.openapi.fileChooser; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.UIBundle; -import org.jetbrains.annotations.NotNull; public class FileChooserDescriptorFactory { - private FileChooserDescriptorFactory() { - } + private FileChooserDescriptorFactory() { } public static FileChooserDescriptor createAllButJarContentsDescriptor() { return new FileChooserDescriptor(true, true, true, true, false, true); @@ -45,13 +44,7 @@ public class FileChooserDescriptorFactory { return new FileChooserDescriptor(true, false, false, false, false, false) { @Override public boolean isFileSelectable(VirtualFile file) { - if (super.isFileSelectable(file)) return true; - - if (SystemInfo.isMac && file.isDirectory() && "app".equals(file.getExtension())) { - return true; - } - - return false; + return super.isFileSelectable(file) || SystemInfo.isMac && file.isDirectory() && "app".equals(file.getExtension()); } }; } @@ -60,6 +53,24 @@ public class FileChooserDescriptorFactory { return new FileChooserDescriptor(true, true, true, true, false, false); } + public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType) { + return new FileChooserDescriptor(true, false, false, false, false, false).withFileFilter(new Condition<VirtualFile>() { + @Override + public boolean value(VirtualFile file) { + return file.getFileType() == fileType; + } + }); + } + + public static FileChooserDescriptor createSingleFileDescriptor(final String extension) { + return new FileChooserDescriptor(true, false, false, false, false, false).withFileFilter(new Condition<VirtualFile>() { + @Override + public boolean value(VirtualFile file) { + return Comparing.equal(file.getExtension(), extension, SystemInfo.isFileSystemCaseSensitive); + } + }); + } + public static FileChooserDescriptor createSingleFolderDescriptor() { return new FileChooserDescriptor(false, true, false, false, false, false); } @@ -72,54 +83,40 @@ public class FileChooserDescriptorFactory { return new FileChooserDescriptor(true, true, false, false, false, false); } - public static FileChooserDescriptor getDirectoryChooserDescriptor(String aSearchedObjectName) { - final FileChooserDescriptor singleFolderDescriptor = createSingleFolderDescriptor(); - singleFolderDescriptor.setTitle(UIBundle.message("file.chooser.select.object.title", aSearchedObjectName)); - return singleFolderDescriptor; + public static FileChooserDescriptor createSingleFileOrFolderDescriptor(final FileType fileType) { + return new FileChooserDescriptor(true, true, false, false, false, false).withFileFilter(new Condition<VirtualFile>() { + @Override + public boolean value(VirtualFile file) { + return file.getFileType() == fileType; + } + }); } - public static FileChooserDescriptor getFileChooserDescriptor(String aSearchedObjectName) { - final FileChooserDescriptor fileChooserDescriptor = createSingleFileNoJarsDescriptor(); - fileChooserDescriptor.setTitle(UIBundle.message("file.chooser.select.object.title", aSearchedObjectName)); - return fileChooserDescriptor; + /** @deprecated use {@link #createSingleFileDescriptor(FileType)} or {@link #createSingleFileOrFolderDescriptor(FileType)} (to be removed in IDEA 14) */ + @SuppressWarnings("UnusedDeclaration") + public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType, final boolean supportDirectories) { + return supportDirectories ? createSingleFileOrFolderDescriptor(fileType) : createSingleFileDescriptor(fileType); } - public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType) { - return createSingleFileDescriptor(fileType, false); + /** @deprecated not very useful (to be removed in IDEA 15) */ + @SuppressWarnings("UnusedDeclaration") + public static FileChooserDescriptor getDirectoryChooserDescriptor(String objectName) { + return createSingleFolderDescriptor().withTitle("Select " + objectName); } - /** - * Creates file descriptor with certain type and (possible) folders. - * @param fileType supported type - * @param supportDirectories support directories or not - * @return descriptor - */ - @NotNull - public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType, final boolean supportDirectories) { - return new FileChooserDescriptor(true, supportDirectories, false, false, false, false) { - @Override - public boolean isFileVisible(final VirtualFile file, final boolean showHiddenFiles) { - return file.isDirectory() || file.getFileType() == fileType; - } - - @Override - public boolean isFileSelectable(final VirtualFile file) { - return super.isFileSelectable(file) && (file.getFileType() == fileType || ((file.isDirectory() && supportDirectories))); - } - }; + /** @deprecated not very useful (to be removed in IDEA 15) */ + @SuppressWarnings("UnusedDeclaration") + public static FileChooserDescriptor getFileChooserDescriptor(String objectName) { + return createSingleFileNoJarsDescriptor().withTitle("Select " + objectName); } - /** - * @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) - */ + /** @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) */ @SuppressWarnings({"UnusedDeclaration", "deprecation"}) public static FileChooserDescriptorBuilder onlyFiles() { return FileChooserDescriptorBuilder.onlyFiles(); } - /** - * @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) - */ + /** @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) */ @SuppressWarnings({"UnusedDeclaration", "deprecation"}) public static FileChooserDescriptorBuilder filesAndFolders() { return FileChooserDescriptorBuilder.filesAndFolders(); diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableBase.java new file mode 100644 index 000000000000..d7c7dca2f19b --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableBase.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.options; + +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implements SearchableConfigurable, Configurable.NoScroll { + private final String id; + private final String displayName; + private final String helpTopic; + + private UI ui; + + protected ConfigurableBase(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic) { + this.id = id; + this.displayName = displayName; + this.helpTopic = helpTopic; + } + + @NotNull + @Override + public final String getId() { + return id; + } + + @Nls + @Override + public final String getDisplayName() { + return displayName; + } + + @Nullable + @Override + public final String getHelpTopic() { + return helpTopic; + } + + @Nullable + @Override + public Runnable enableSearch(String option) { + return null; + } + + @NotNull + protected abstract S getSettings(); + + @Override + public void reset() { + if (ui != null) { + ui.reset(getSettings()); + } + } + + @Nullable + @Override + public final JComponent createComponent() { + if (ui == null) { + ui = createUi(); + } + return ui.getComponent(); + } + + protected abstract UI createUi(); + + @Override + public final boolean isModified() { + return ui != null && ui.isModified(getSettings()); + } + + @Override + public final void apply() { + if (ui != null) { + ui.apply(getSettings()); + } + } + + @Override + public void disposeUIResources() { + ui = null; + } +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java index 11c8bdd90052..78a4c1ece130 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java @@ -93,6 +93,9 @@ public class ConfigurableEP<T extends UnnamedConfigurable> extends AbstractExten @Attribute("groupId") public String groupId; + @Attribute("groupWeight") + public int groupWeight; + /** Marks project level configurables that do not apply to the default project. */ @Attribute("nonDefaultProject") public boolean nonDefaultProject; diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableUi.java new file mode 100644 index 000000000000..0ecb19a7ce8e --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableUi.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.options; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public interface ConfigurableUi<S> { + void reset(@NotNull S settings); + + boolean isModified(@NotNull S settings); + + void apply(@NotNull S settings); + + @NotNull + JComponent getComponent(); +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java index aa6d9618482a..34eaf920d78d 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java @@ -41,21 +41,25 @@ public abstract class ShowSettingsUtil { public abstract boolean editConfigurable(@Nullable Project project, Configurable configurable, @Nullable Runnable advancedInitialization); - public abstract boolean editConfigurable(Component parent, Configurable configurable); + public abstract boolean editConfigurable(@Nullable Component parent, @NotNull Configurable configurable); - public abstract boolean editConfigurable(Component parent, Configurable configurable, Runnable advancedInitialization); + public abstract boolean editConfigurable(Component parent, Configurable configurable, @NotNull Runnable advancedInitialization); public abstract boolean editConfigurable(Project project, @NonNls String dimensionServiceKey, Configurable configurable); + public abstract boolean editConfigurable(Project project, @NonNls String dimensionServiceKey, Configurable configurable, boolean showApplyButton); + public abstract boolean editConfigurable(Component parent, String dimensionServiceKey, Configurable configurable); /** * @deprecated create a new instance of configurable instead + * to remove in IDEA 15 */ public abstract <T extends Configurable> T findProjectConfigurable(Project project, Class<T> confClass); /** * @deprecated create a new instance of configurable instead + * to remove in IDEA 15 */ public abstract <T extends Configurable> T findApplicationConfigurable(Class<T> confClass); diff --git a/platform/platform-api/src/com/intellij/openapi/options/SimpleConfigurable.java b/platform/platform-api/src/com/intellij/openapi/options/SimpleConfigurable.java new file mode 100644 index 000000000000..9812165932a2 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/options/SimpleConfigurable.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.options; + +import com.intellij.openapi.util.Getter; +import com.intellij.util.ReflectionUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class SimpleConfigurable<UI extends ConfigurableUi<S>, S> extends ConfigurableBase<UI, S> { + private final Class<UI> uiClass; + private final Getter<S> settingsGetter; + + private SimpleConfigurable(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) { + super(id, displayName, helpTopic); + + this.uiClass = uiClass; + this.settingsGetter = settingsGetter; + } + + public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) { + return new SimpleConfigurable<UI, S>(id, displayName, helpTopic, uiClass, settingsGetter); + } + + public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) { + return create(id, displayName, id, uiClass, settingsGetter); + } + + @NotNull + @Override + protected S getSettings() { + return settingsGetter.get(); + } + + @Override + protected UI createUi() { + return ReflectionUtil.newInstance(uiClass); + } +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java index 8dbe02228bae..59f99ad46a05 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java @@ -18,6 +18,7 @@ package com.intellij.openapi.ui; import com.intellij.icons.AllIcons; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.ui.components.panels.NonOpaquePanel; @@ -45,7 +46,7 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{ public Banner() { setLayout(new BorderLayout()); - setBorder(new EmptyBorder(2, 6, 2, 4)); + setBorder(new EmptyBorder(2, Registry.is("ide.new.settings.dialog") ? 12 : 6, 2, 4)); myProjectIcon.setVisible(false); myProjectIcon.setBorder(new EmptyBorder(0, 12, 0, 4)); diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java index 463d950ae900..00440b0dd8a6 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java @@ -17,6 +17,7 @@ package com.intellij.openapi.ui; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.ArrayUtil; @@ -65,47 +66,54 @@ public class DetailsComponent { protected void paintComponent(final Graphics g) { if (NullableComponent.Check.isNull(myContent) || !myDetailsEnabled) return; - GraphicsConfig c = new GraphicsConfig(g); - c.setAntialiasing(true); - - Insets insets = getInsets(); - if (insets == null) { - insets = new Insets(0, 0, 0, 0); + GraphicsConfig c = null; + Insets insets = null; + final int leftX; + final int rightX; + final int rightY; + if (!Registry.is("ide.new.settings.dialog")) { + c = new GraphicsConfig(g); + c.setAntialiasing(true); + + insets = getInsets(); + if (insets == null) { + insets = new Insets(0, 0, 0, 0); + } + + g.setColor(UIUtil.getFocusedFillColor()); + + final Rectangle banner = myBanner.getBounds(); + final GeneralPath header = new GeneralPath(); + + leftX = insets.left; + final int leftY = insets.top; + rightX = insets.left + getWidth() - 1 - insets.right; + rightY = banner.y + banner.height; + + header.moveTo(leftX, rightY); + int arc = 8; + header.lineTo(leftX, leftY + arc); + header.quadTo(leftX, leftY, leftX + arc, leftY); + header.lineTo(rightX - arc, leftY); + header.quadTo(rightX, leftY, rightX, leftY + arc); + header.lineTo(rightX, rightY); + header.closePath(); + + c.getG().fill(header); + + g.setColor(UIUtil.getFocusedBoundsColor()); + + c.getG().draw(header); + + + if (myPaintBorder) { + final int down = getHeight() - insets.top - insets.bottom - 1; + g.drawLine(leftX, rightY, leftX, down); + g.drawLine(rightX, rightY, rightX, down); + g.drawLine(leftX, down, rightX, down); + } + c.restore(); } - - g.setColor(UIUtil.getFocusedFillColor()); - - final Rectangle banner = myBanner.getBounds(); - final GeneralPath header = new GeneralPath(); - - final int leftX = insets.left; - final int leftY = insets.top; - final int rightX = insets.left + getWidth() - 1 - insets.right; - final int rightY = banner.y + banner.height; - - header.moveTo(leftX, rightY); - int arc = 8; - header.lineTo(leftX, leftY + arc); - header.quadTo(leftX, leftY, leftX + arc, leftY); - header.lineTo(rightX - arc, leftY); - header.quadTo(rightX, leftY, rightX, leftY + arc); - header.lineTo(rightX, rightY); - header.closePath(); - - c.getG().fill(header); - - g.setColor(UIUtil.getFocusedBoundsColor()); - - c.getG().draw(header); - - if (myPaintBorder) { - final int down = getHeight() - insets.top - insets.bottom - 1; - g.drawLine(leftX, rightY, leftX, down); - g.drawLine(rightX, rightY, rightX, down); - g.drawLine(leftX, down, rightX, down); - } - - c.restore(); } }; diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java index ed374a905462..e4c8c6852727 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogBuilder.java @@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NonNls; @@ -55,26 +56,34 @@ public class DialogBuilder implements Disposable { return showImpl(true).getExitCode(); } + public boolean showAndGet() { + return showImpl(true).isOK(); + } + public void showNotModal() { showImpl(false); } - public DialogBuilder(Project project) { + public DialogBuilder(@Nullable Project project) { myDialogWrapper = new MyDialogWrapper(project, true); Disposer.register(myDialogWrapper.getDisposable(), this); } - public DialogBuilder(Component parent) { + public DialogBuilder(@Nullable Component parent) { myDialogWrapper = new MyDialogWrapper(parent, true); Disposer.register(myDialogWrapper.getDisposable(), this); } + public DialogBuilder() { + this(((Project)null)); + } + @Override public void dispose() { } private MyDialogWrapper showImpl(boolean isModal) { - LOG.assertTrue(myTitle != null && myTitle.trim().length() != 0, + LOG.assertTrue(!StringUtil.isEmptyOrSpaces(myTitle), String.format("Dialog title shouldn't be empty or null: [%s]", myTitle)); myDialogWrapper.setTitle(myTitle); myDialogWrapper.init(); @@ -91,6 +100,12 @@ public class DialogBuilder implements Disposable { } @NotNull + public DialogBuilder centerPanel(@NotNull JComponent centerPanel) { + myCenterPanel = centerPanel; + return this; + } + + @NotNull public DialogBuilder setNorthPanel(@NotNull JComponent northPanel) { myNorthPanel = northPanel; return this; @@ -100,6 +115,7 @@ public class DialogBuilder implements Disposable { myTitle = title; } + @NotNull public DialogBuilder title(@NotNull String title) { myTitle = title; return this; @@ -196,6 +212,18 @@ public class DialogBuilder implements Disposable { myDialogWrapper.setOKActionEnabled(isEnabled); } + @NotNull + public DialogBuilder okActionEnabled(boolean isEnabled) { + myDialogWrapper.setOKActionEnabled(isEnabled); + return this; + } + + @NotNull + public DialogBuilder resizable(boolean resizable) { + myDialogWrapper.setResizable(resizable); + return this; + } + public CustomizableAction getOkAction() { return get(getActionDescriptors(), OkActionDescriptor.class); } @@ -267,7 +295,7 @@ public class DialogBuilder implements Disposable { protected Action createAction(final DialogWrapper dialogWrapper) { return new AbstractAction(){ @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { dialogWrapper.close(myExitCode); } }; @@ -325,7 +353,7 @@ public class DialogBuilder implements Disposable { private class MyDialogWrapper extends DialogWrapper { private String myHelpId = null; - private MyDialogWrapper(Project project, boolean canBeParent) { + private MyDialogWrapper(@Nullable Project project, boolean canBeParent) { super(project, canBeParent); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 75cb4de7af74..741f67dee2c4 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -1233,6 +1233,7 @@ public abstract class DialogWrapper { if (SystemInfo.isWindows) { installEnterHook(root); } + myErrorTextAlarm.setActivationComponent(root); } @NotNull @@ -1838,15 +1839,14 @@ public abstract class DialogWrapper { return; } myLastErrorText = text; - if (myActualSize == null && !StringUtil.isEmpty(text)) { - myActualSize = getSize(); - } - myErrorTextAlarm.cancelAllRequests(); myErrorTextAlarm.addRequest(new Runnable() { @Override public void run() { final String text = myLastErrorText; + if (myActualSize == null && !StringUtil.isEmpty(text)) { + myActualSize = getSize(); + } myErrorText.setError(text); if (text != null && text.length() > myMaxErrorTextLength) { // during the first update, resize only for growing. during a subsequent update, diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeerFactory.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeerFactory.java index c9515a884f97..c1239e523896 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeerFactory.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeerFactory.java @@ -24,17 +24,24 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; public abstract class DialogWrapperPeerFactory { + @NotNull public static DialogWrapperPeerFactory getInstance() { if (ApplicationManager.getApplication() == null) { - try { - return (DialogWrapperPeerFactory)Class.forName("com.intellij.openapi.ui.impl.DialogWrapperPeerFactoryImpl").newInstance(); - } - catch (Exception e) { - throw new RuntimeException("Can't instantiate DialogWrapperPeerFactory", e); - } + return getInstanceByName(); } - return ServiceManager.getService(DialogWrapperPeerFactory.class); + DialogWrapperPeerFactory factory = ServiceManager.getService(DialogWrapperPeerFactory.class); + return factory == null ? getInstanceByName() : factory; + } + + @NotNull + private static DialogWrapperPeerFactory getInstanceByName() { + try { + return (DialogWrapperPeerFactory)Class.forName("com.intellij.openapi.ui.impl.DialogWrapperPeerFactoryImpl").newInstance(); + } + catch (Exception e) { + throw new RuntimeException("Can't instantiate DialogWrapperPeerFactory", e); + } } @NotNull diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java index ab193aff20c2..7819ef68a7e5 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java @@ -40,6 +40,7 @@ public abstract class MessageDialogBuilder<T extends MessageDialogBuilder> { myMessage = message; } + @NotNull public static YesNo yesNo(@NotNull String title, @NotNull String message) { return new YesNo(title, message).icon(Messages.getQuestionIcon()); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index dae35d4b685d..1a07b33d696d 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -143,9 +143,12 @@ public class Messages { try { if (canShowMacSheetPanel()) { - Window parentWindow = WindowManager.getInstance().suggestParentWindow(project); - return MacMessages.getInstance() - .showMessageDialog(title, message, options, false, parentWindow, defaultOptionIndex, defaultOptionIndex, doNotAskOption); + WindowManager windowManager = WindowManager.getInstance(); + if (windowManager != null) { + Window parentWindow = windowManager.suggestParentWindow(project); + return MacMessages.getInstance() + .showMessageDialog(title, message, options, false, parentWindow, defaultOptionIndex, defaultOptionIndex, doNotAskOption); + } } } catch (Exception exception) { diff --git a/platform/platform-api/src/com/intellij/openapi/util/PasswordUtil.java b/platform/platform-api/src/com/intellij/openapi/util/PasswordUtil.java index 4ba3fa7c1516..c4995a34ac27 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/PasswordUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/util/PasswordUtil.java @@ -15,13 +15,17 @@ */ package com.intellij.openapi.util; +import org.jetbrains.annotations.Nullable; + public class PasswordUtil { private PasswordUtil() { } // weak encryption just to avoid plain text passwords in text files - public static String encodePassword(String password) { + public static String encodePassword(@Nullable String password) { String result = ""; - if (password == null) return result; + if (password == null) { + return result; + } for (int i = 0; i < password.length(); i++) { int c = password.charAt(i); c ^= 0xdfaa; @@ -30,9 +34,11 @@ public class PasswordUtil { return result; } - public static String decodePassword(String password) throws NumberFormatException { + public static String decodePassword(@Nullable String password) throws NumberFormatException { String result = ""; - if (password == null) return result; + if (password == null) { + return result; + } for (int i = 0; i < password.length(); i += 4) { String s = password.substring(i, i + 4); int c = Integer.parseInt(s, 16); diff --git a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java index 7a6c15ef495f..cf10656a24ed 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java +++ b/platform/platform-api/src/com/intellij/openapi/util/registry/RegistryState.java @@ -16,9 +16,14 @@ package com.intellij.openapi.util.registry; import com.intellij.openapi.components.*; +import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + @State( name = "Registry", storages = { @@ -26,6 +31,7 @@ import org.jetbrains.annotations.NotNull; file = StoragePathMacros.APP_CONFIG + "/other.xml")} ) public class RegistryState implements BaseComponent, PersistentStateComponent<Element> { + private static final Logger LOG = Logger.getInstance(RegistryState.class); public RegistryState() { } @@ -36,6 +42,14 @@ public class RegistryState implements BaseComponent, PersistentStateComponent<El public void loadState(Element state) { Registry.getInstance().loadState(state); + SortedMap<String, String> userProperties = new TreeMap<String, String>(Registry.getInstance().getUserProperties()); + userProperties.remove("ide.firstStartup"); + if (!userProperties.isEmpty()) { + LOG.info("Registry values changed by user:"); + for (Map.Entry<String, String> entry : userProperties.entrySet()) { + LOG.info(" " + entry.getKey() + " = " + entry.getValue()); + } + } } @NotNull diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowId.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowId.java index edcf3b87ae2a..7adbfd16b324 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowId.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowId.java @@ -38,4 +38,5 @@ public interface ToolWindowId { String DOCUMENTATION = UIBundle.message("tool.window.name.documentation"); String TASKS = UIBundle.message("tool.window.name.tasks"); String DATABASE_VIEW = UIBundle.message("tool.window.name.database"); + String PREVIEW = UIBundle.message("tool.window.name.preview"); }
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java index b7ec8556f3d9..67ca238ce077 100644 --- a/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -30,8 +31,15 @@ public abstract class ColoredListCellRenderer<T> extends SimpleColoredComponent protected boolean mySelected; protected Color myForeground; protected Color mySelectionForeground; + @Nullable + private final JComboBox myComboBox; public ColoredListCellRenderer() { + this(null); + } + + public ColoredListCellRenderer(@Nullable JComboBox comboBox) { + myComboBox = comboBox; setFocusBorderAroundIcon(true); getIpad().left = UIUtil.getListCellHPadding(); getIpad().right = UIUtil.getListCellHPadding(); @@ -40,6 +48,9 @@ public abstract class ColoredListCellRenderer<T> extends SimpleColoredComponent public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) { clear(); + if (myComboBox != null) { + setEnabled(myComboBox.isEnabled()); + } setFont(list.getFont()); mySelected = selected; myForeground = list.getForeground(); diff --git a/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java b/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java index 76bacb9cb452..a2e8aacc046f 100644 --- a/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/GroupedElementsRenderer.java @@ -165,22 +165,22 @@ public abstract class GroupedElementsRenderer { } @Override - protected final Color getSelectionBackground() { + protected Color getSelectionBackground() { return UIUtil.getTreeSelectionBackground(); } @Override - protected final Color getSelectionForeground() { + protected Color getSelectionForeground() { return UIUtil.getTreeSelectionForeground(); } @Override - protected final Color getBackground() { + protected Color getBackground() { return UIUtil.getTreeTextBackground(); } @Override - protected final Color getForeground() { + protected Color getForeground() { return UIUtil.getTreeTextForeground(); } } diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java index ec378977f76e..9d5dcbea7edf 100644 --- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java +++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.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. @@ -26,7 +26,7 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; @@ -47,11 +47,9 @@ import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; public class GuiUtils { - private static final Insets paddingFromDialogBoundaries = new Insets(7, 5, 7, 5); private static final Insets paddingInsideDialog = new Insets(5, 5, 5, 5); - public static final int lengthForFileField = 25; private static final CharFilter NOT_MNEMONIC_CHAR_FILTER = new CharFilter() { @Override public boolean accept(char ch) { @@ -78,33 +76,33 @@ public class GuiUtils { return result; } - public static JPanel constructDirectoryBrowserField(final JTextField aTextField, final String aSearchedObjectName) { - return constructFieldWithBrowseButton(aTextField, new ActionListener() { + public static JPanel constructDirectoryBrowserField(final JTextField field, final String objectName) { + return constructFieldWithBrowseButton(field, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - FileChooserDescriptor descriptor = FileChooserDescriptorFactory.getDirectoryChooserDescriptor(aSearchedObjectName); - VirtualFile file = FileChooser.chooseFile(descriptor, aTextField, null, null); + FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle("Select " + objectName); + VirtualFile file = FileChooser.chooseFile(descriptor, field, null, null); if (file != null) { - aTextField.setText(FileUtil.toSystemDependentName(file.getPath())); - aTextField.postActionEvent(); + field.setText(FileUtil.toSystemDependentName(file.getPath())); + field.postActionEvent(); } } }); } - public static JPanel constructFileURLBrowserField(final TextFieldWithHistory aFieldWithHistory, - final String aSearchedObjectName) { - return constructFieldWithBrowseButton(aFieldWithHistory, new ActionListener() { + public static JPanel constructFileURLBrowserField(final TextFieldWithHistory field, final String objectName) { + return constructFieldWithBrowseButton(field, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - FileChooserDescriptor descriptor = FileChooserDescriptorFactory.getFileChooserDescriptor(aSearchedObjectName); - VirtualFile file = FileChooser.chooseFile(descriptor, aFieldWithHistory, null, null); + FileChooserDescriptor descriptor = + FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle("Select " + objectName); + VirtualFile file = FileChooser.chooseFile(descriptor, field, null, null); if (file != null) { try { - aFieldWithHistory.setText(VfsUtil.virtualToIoFile(file).toURL().toString()); + field.setText(VfsUtilCore.virtualToIoFile(file).toURI().toURL().toString()); } catch (MalformedURLException e1) { - aFieldWithHistory.setText(""); + field.setText(""); } } } diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java index 27324c9d9781..6a99624a620b 100644 --- a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.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. @@ -20,9 +20,11 @@ import com.intellij.ide.BrowserUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.util.NotNullProducer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.PlatformColors; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -42,7 +44,14 @@ import java.util.List; * @author Eugene Belyaev */ public class HyperlinkLabel extends HighlightableComponent { - private static final TextAttributes BOLD_ATTRIBUTES = new TextAttributes(UIUtil.getLabelTextForeground(), null, null, null, Font.BOLD); + private static final TextAttributes BOLD_ATTRIBUTES = new TextAttributes(new JBColor(new NotNullProducer<Color>() { + @NotNull + @Override + public Color produce() { + final Color foreground = UIUtil.getLabelTextForeground(); + return foreground == null ? UIUtil.getLabelForeground() : foreground; + } + }), null, null, null, Font.BOLD); private static final Logger LOG = Logger.getInstance(HyperlinkLabel.class.getName()); @@ -59,7 +68,13 @@ public class HyperlinkLabel extends HighlightableComponent { public HyperlinkLabel(String text) { this(text, PlatformColors.BLUE, - UIUtil.getLabelBackground(), + new JBColor(new NotNullProducer<Color>() { + @NotNull + @Override + public Color produce() { + return UIUtil.getLabelBackground(); + } + }), PlatformColors.BLUE); } @@ -209,7 +224,9 @@ public class HyperlinkLabel extends HighlightableComponent { LOG.error(e); } highlightedText.applyToComponent(this); - ((JComponent)getParent()).revalidate(); + final JComponent parent = (JComponent)getParent(); + parent.revalidate(); + parent.repaint(); adjustSize(); } diff --git a/platform/platform-api/src/com/intellij/ui/InplaceButton.java b/platform/platform-api/src/com/intellij/ui/InplaceButton.java index 04ea9161f99c..89dd0dfc34e2 100644 --- a/platform/platform-api/src/com/intellij/ui/InplaceButton.java +++ b/platform/platform-api/src/com/intellij/ui/InplaceButton.java @@ -101,7 +101,11 @@ public class InplaceButton extends JComponent implements ActiveComponent { setIcons(source.getRegular(), source.getInactive(), source.getHovered()); } - public void setIcons(final Icon regular, final Icon inactive, final Icon hovered) { + public void setIcons(final Icon regular, Icon inactive, Icon hovered) { + if (regular == null) return; + if (inactive == null) inactive = regular; + if (hovered == null) hovered = regular; + int width = Math.max(regular.getIconWidth(), inactive.getIconWidth()); width = Math.max(width, hovered.getIconWidth()); int height = Math.max(regular.getIconHeight(), inactive.getIconHeight()); diff --git a/platform/platform-api/src/com/intellij/ui/JBListWithHintProvider.java b/platform/platform-api/src/com/intellij/ui/JBListWithHintProvider.java index 5ef516210e0d..f859421bbbee 100644 --- a/platform/platform-api/src/com/intellij/ui/JBListWithHintProvider.java +++ b/platform/platform-api/src/com/intellij/ui/JBListWithHintProvider.java @@ -18,79 +18,59 @@ package com.intellij.ui; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.psi.PsiElement; import com.intellij.ui.components.JBList; -import com.intellij.ui.popup.PopupUpdateProcessorBase; +import com.intellij.ui.popup.HintUpdateSupply; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.util.Collection; /** * @author pegov + * @deprecated + * @see com.intellij.ui.popup.HintUpdateSupply */ public abstract class JBListWithHintProvider extends JBList { - private JBPopup myHint; + { + new HintUpdateSupply(this) { + @Override + protected PsiElement getPsiElementForHint(Object selectedValue) { + return JBListWithHintProvider.this.getPsiElementForHint(selectedValue); + } + }; + } public JBListWithHintProvider() { - addSelectionListener(); } public JBListWithHintProvider(ListModel dataModel) { super(dataModel); - addSelectionListener(); } public JBListWithHintProvider(Object... listData) { super(listData); - addSelectionListener(); } public JBListWithHintProvider(Collection items) { super(items); - addSelectionListener(); } - private void addSelectionListener() { - addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(final ListSelectionEvent e) { - if (getClientProperty(ListUtil.SELECTED_BY_MOUSE_EVENT) != Boolean.TRUE) { - final Object[] selectedValues = ((JList)e.getSource()).getSelectedValues(); - if (selectedValues.length != 1) return; - - final PsiElement element = getPsiElementForHint(selectedValues[0]); - if (element != null && element.isValid()) { - updateHint(element); - } - } - } - }); - } - @Nullable protected abstract PsiElement getPsiElementForHint(final Object selectedValue); - public void registerHint(final JBPopup hint) { - hideHint(); - myHint = hint; + @Deprecated + public void registerHint(JBPopup hint) { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).registerHint(hint); } - - public void hideHint() { - if (myHint != null && myHint.isVisible()) { - myHint.cancel(); - } - myHint = null; + @Deprecated + public void hideHint() { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).hideHint(); } - - public void updateHint(PsiElement element) { - if (myHint == null || !myHint.isVisible()) return; - final PopupUpdateProcessorBase updateProcessor = myHint.getUserData(PopupUpdateProcessorBase.class); - if (updateProcessor != null) { - updateProcessor.updatePopup(element); - } + @Deprecated + public void updateHint(PsiElement element) { + ObjectUtils.assertNotNull(HintUpdateSupply.getSupply(this)).updateHint(element); } - + } diff --git a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java index 75769d25c0db..74fe7bb31108 100644 --- a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java +++ b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java @@ -56,22 +56,14 @@ public class ScreenUtil { } public static Rectangle getMainScreenBounds() { - GraphicsConfiguration graphicsConfiguration = - GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - Rectangle bounds = graphicsConfiguration.getBounds(); - applyInsets(bounds, getScreenInsets(graphicsConfiguration)); - return bounds; + return getScreenRectangle(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()); } private static Rectangle[] getAllScreenBounds() { - final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - final GraphicsDevice[] devices = env.getScreenDevices(); + GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); Rectangle[] result = new Rectangle[devices.length]; for (int i = 0; i < devices.length; i++) { - GraphicsDevice device = devices[i]; - GraphicsConfiguration configuration = device.getDefaultConfiguration(); - result[i] = new Rectangle(configuration.getBounds()); - applyInsets(result[i], getScreenInsets(configuration)); + result[i] = getScreenRectangle(devices[i]); } return result; } @@ -86,27 +78,7 @@ public class ScreenUtil { } public static Rectangle getScreenRectangle(@NotNull Point p) { - double distance = -1; - Rectangle answer = null; - - Rectangle[] allScreenBounds = getAllScreenBounds(); - for (Rectangle rect : allScreenBounds) { - if (rect.contains(p)) { - return rect; - } - - final double d = findNearestPointOnBorder(rect, p).distance(p.x, p.y); - if (answer == null || distance > d) { - distance = d; - answer = rect; - } - } - - if (answer == null) { - throw new IllegalStateException("It's impossible to determine target graphics environment for point (" + p.x + "," + p.y + ")"); - } - - return answer; + return getScreenRectangle(p.x, p.y); } public static GraphicsDevice getScreenDevice(Rectangle bounds) { @@ -150,11 +122,12 @@ public class ScreenUtil { } private static Rectangle applyInsets(Rectangle rect, Insets i) { - if (i == null) { - return rect; - } - - return new Rectangle(rect.x + i.left, rect.y + i.top, rect.width - (i.left + i.right), rect.height - (i.top + i.bottom)); + return (i == null) + ? new Rectangle(rect) + : new Rectangle(rect.x + i.left, + rect.y + i.top, + rect.width - (i.left + i.right), + rect.height - (i.top + i.bottom)); } public static Insets getScreenInsets(final GraphicsConfiguration gc) { @@ -181,8 +154,83 @@ public class ScreenUtil { return Toolkit.getDefaultToolkit().getScreenInsets(gc); } + /** + * Returns a visible area for the specified graphics device. + * + * @param device one of available devices + * @return a visible area rectangle + */ + private static Rectangle getScreenRectangle(GraphicsDevice device) { + GraphicsConfiguration configuration = device.getDefaultConfiguration(); + return applyInsets(configuration.getBounds(), getScreenInsets(configuration)); + } + + /** + * Finds a device that is the closest to the specified point and + * returns its visible area. + * + * @param x the X coordinate of the specified point + * @param y the Y coordinate of the specified point + * @return a visible area rectangle + */ public static Rectangle getScreenRectangle(int x, int y) { - return getScreenRectangle(new Point(x, y)); + GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + if (devices.length == 0) { + return new Rectangle(x, y, 0, 0); + } + if (devices.length == 1) { + return getScreenRectangle(devices[0]); + } + Rectangle[] rectangles = new Rectangle[devices.length]; + for (int i = 0; i < devices.length; i++) { + GraphicsConfiguration configuration = devices[i].getDefaultConfiguration(); + Rectangle bounds = configuration.getBounds(); + rectangles[i] = applyInsets(bounds, getScreenInsets(configuration)); + if (bounds.contains(x, y)) { + return rectangles[i]; + } + } + Rectangle bounds = rectangles[0]; + int minimum = distance(bounds, x, y); + for (int i = 1; i < rectangles.length; i++) { + int distance = distance(rectangles[i], x, y); + if (minimum > distance) { + minimum = distance; + bounds = rectangles[i]; + } + } + return bounds; + } + + /** + * Normalizes a specified value in the specified range. + * If value less than the minimal value, + * the method returns the minimal value. + * If value greater than the maximal value, + * the method returns the maximal value. + * + * @param value the value to normalize + * @param min the minimal value of the range + * @param max the maximal value of the range + * @return a normalized value + */ + private static int normalize(int value, int min, int max) { + return value < min ? min : value > max ? max : value; + } + + /** + * Returns a square of the distance from + * the specified point to the specified rectangle, + * which does not contain the specified point. + * + * @param x the X coordinate of the specified point + * @param y the Y coordinate of the specified point + * @return a square of the distance + */ + private static int distance(Rectangle bounds, int x, int y) { + x -= normalize(x, bounds.x, bounds.x + bounds.width); + y -= normalize(y, bounds.y, bounds.y + bounds.height); + return x * x + y * y; } public static boolean isOutsideOnTheRightOFScreen(Rectangle rect) { diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java index 97a42176a25b..51535b67f9af 100644 --- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java +++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java @@ -235,7 +235,7 @@ public class JBScrollPane extends JScrollPane { } if (colHead != null) { Rectangle headerBounds = colHead.getBounds(); - headerBounds.width = viewportBounds.width - headerBounds.x; + headerBounds.width = viewportBounds.width; colHead.setBounds(headerBounds); } hideFromView(layout.getCorner(UPPER_RIGHT_CORNER)); @@ -249,7 +249,7 @@ public class JBScrollPane extends JScrollPane { } if (rowHead != null) { Rectangle headerBounds = rowHead.getBounds(); - headerBounds.height = viewportBounds.height - headerBounds.y; + headerBounds.height = viewportBounds.height; rowHead.setBounds(headerBounds); } diff --git a/platform/platform-api/src/com/intellij/ui/popup/HintUpdateSupply.java b/platform/platform-api/src/com/intellij/ui/popup/HintUpdateSupply.java new file mode 100644 index 000000000000..54b071ab0b94 --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/popup/HintUpdateSupply.java @@ -0,0 +1,156 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ui.popup; + +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiElement; +import com.intellij.ui.ListUtil; +import com.intellij.ui.components.JBList; +import com.intellij.ui.table.JBTable; +import com.intellij.ui.treeStructure.Tree; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; + +/** + * Use this class to make various hints like QuickDocumentation, ShowImplementations, etc. + * respond to the selection change in the original component like ProjectView, various GoTo popups, etc. + * + * @author gregsh + */ +public abstract class HintUpdateSupply { + private static final Key<HintUpdateSupply> HINT_UPDATE_MARKER = Key.create("HINT_UPDATE_MARKER"); + + @Nullable + private JBPopup myHint; + + @Nullable + public static HintUpdateSupply getSupply(@NotNull JComponent component) { + return (HintUpdateSupply)component.getClientProperty(HINT_UPDATE_MARKER); + } + + public static void hideHint(@NotNull JComponent component) { + HintUpdateSupply supply = getSupply(component); + if (supply != null) supply.hideHint(); + } + + protected HintUpdateSupply(@NotNull JComponent component) { + installSupply(component); + } + + public HintUpdateSupply(@NotNull final JBTable table) { + installSupply(table); + ListSelectionListener listener = new ListSelectionListener() { + @Override + public void valueChanged(final ListSelectionEvent e) { + if (!isHintVisible(HintUpdateSupply.this.myHint) || isSelectedByMouse(table)) return; + + int selected = ((ListSelectionModel)e.getSource()).getLeadSelectionIndex(); + int rowCount = table.getRowCount(); + if (selected == -1 || rowCount == 0) return; + + PsiElement element = getPsiElementForHint(table.getValueAt(Math.min(selected, rowCount - 1), 0)); + if (element != null && element.isValid()) { + updateHint(element); + } + } + }; + table.getSelectionModel().addListSelectionListener(listener); + table.getColumnModel().getSelectionModel().addListSelectionListener(listener); + } + + public HintUpdateSupply(@NotNull final Tree tree) { + installSupply(tree); + tree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(final TreeSelectionEvent e) { + if (!isHintVisible(HintUpdateSupply.this.myHint) || isSelectedByMouse(tree)) return; + + TreePath path = tree.getSelectionPath(); + if (path != null) { + final PsiElement psiElement = getPsiElementForHint(path.getLastPathComponent()); + if (psiElement != null && psiElement.isValid()) { + updateHint(psiElement); + } + } + } + }); + } + + public HintUpdateSupply(@NotNull final JBList list) { + installSupply(list); + list.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(final ListSelectionEvent e) { + if (!isHintVisible(HintUpdateSupply.this.myHint) || isSelectedByMouse(list)) return; + + Object[] selectedValues = ((JList)e.getSource()).getSelectedValues(); + if (selectedValues.length != 1) return; + + PsiElement element = getPsiElementForHint(selectedValues[0]); + if (element != null && element.isValid()) { + updateHint(element); + } + } + }); + } + + @Nullable + protected abstract PsiElement getPsiElementForHint(@Nullable Object selectedValue); + + private void installSupply(@NotNull JComponent component) { + component.putClientProperty(HINT_UPDATE_MARKER, this); + } + + public void registerHint(JBPopup hint) { + hideHint(); + myHint = hint; + } + + public void hideHint() { + if (isHintVisible(myHint)) { + myHint.cancel(); + } + + myHint = null; + } + + public void updateHint(PsiElement element) { + if (!isHintVisible(myHint)) return; + + PopupUpdateProcessorBase updateProcessor = myHint.getUserData(PopupUpdateProcessorBase.class); + if (updateProcessor != null) { + updateProcessor.updatePopup(element); + } + } + + @Contract("!null->true") + private static boolean isHintVisible(JBPopup hint) { + return hint != null && hint.isVisible(); + } + + private static boolean isSelectedByMouse(@NotNull JComponent c) { + return Boolean.TRUE.equals(c.getClientProperty(ListUtil.SELECTED_BY_MOUSE_EVENT)); + } +} diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index bda230eb767e..c1146be40aba 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -424,7 +424,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component if (e instanceof KeyEvent) { // do not start editing in autoStartsEdit mode on Ctrl-Z and other non-typed events - if (!UIUtil.isReallyTypedEvent((KeyEvent)e)) return false; + if (!UIUtil.isReallyTypedEvent((KeyEvent)e) || ((KeyEvent)e).getKeyChar() == KeyEvent.CHAR_UNDEFINED) return false; SpeedSearchSupply supply = SpeedSearchSupply.getSupply(this); if (supply != null && supply.isPopupActive()) { @@ -743,7 +743,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component @Override public void setColor(Color color) { - if (!UIUtil.isUnderDarcula() || !JBTable.this.getBackground().equals(color)) { + if (color != null && (!UIUtil.isUnderDarcula() || !JBTable.this.getBackground().equals(color))) { //noinspection UseJBColor color = new Color(UIUtil.getGrayFilter().filterRGB(0, 0, color.getRGB())); } diff --git a/platform/platform-api/src/com/intellij/util/PlatformUtils.java b/platform/platform-api/src/com/intellij/util/PlatformUtils.java index 064b5ccc48b6..dfcb5ccf624f 100644 --- a/platform/platform-api/src/com/intellij/util/PlatformUtils.java +++ b/platform/platform-api/src/com/intellij/util/PlatformUtils.java @@ -28,7 +28,7 @@ public class PlatformUtils { public static final String IDEA_PREFIX = PlatformUtilsCore.IDEA_PREFIX; public static final String IDEA_CE_PREFIX = PlatformUtilsCore.COMMUNITY_PREFIX; public static final String APPCODE_PREFIX = PlatformUtilsCore.APPCODE_PREFIX; - public static final String CPP_PREFIX = PlatformUtilsCore.CPP_PREFIX; + public static final String CLION_PREFIX = PlatformUtilsCore.CLION_PREFIX; public static final String PYCHARM_PREFIX = PlatformUtilsCore.PYCHARM_PREFIX; public static final String PYCHARM_CE_PREFIX = PlatformUtilsCore.PYCHARM_PREFIX2; public static final String RUBY_PREFIX = PlatformUtilsCore.RUBY_PREFIX; @@ -66,12 +66,12 @@ public class PlatformUtils { return PlatformUtilsCore.isAppCode(); } - public static boolean isCppIde() { - return PlatformUtilsCore.isCppIde(); + public static boolean isCLion() { + return PlatformUtilsCore.isCLion(); } public static boolean isCidr() { - return isAppCode() || isCppIde(); + return isAppCode() || isCLion(); } public static boolean isPyCharm() { diff --git a/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java b/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java index 246f1e449d5d..83cca8a039df 100644 --- a/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java +++ b/platform/platform-api/src/com/intellij/util/net/AuthenticationDialog.java @@ -23,13 +23,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -/** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Oct 7, 2003 - * Time: 3:56:25 PM - * To change this template use Options | File Templates. - */ public class AuthenticationDialog extends DialogWrapper { private final AuthenticationPanel panel; @@ -42,7 +35,7 @@ public class AuthenticationDialog extends DialogWrapper { final Window window = getWindow(); if (window instanceof JDialog) { - ((JDialog) window).setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + ((JDialog) window).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); } init(); @@ -57,7 +50,7 @@ public class AuthenticationDialog extends DialogWrapper { final Window window = getWindow(); if (window instanceof JDialog) { - ((JDialog) window).setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + ((JDialog) window).setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); } init(); @@ -69,6 +62,7 @@ public class AuthenticationDialog extends DialogWrapper { return panel.getPreferredFocusedComponent(); } + @Override @Nullable protected JComponent createCenterPanel() { return panel; diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsDialog.java b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsDialog.java index 52dfa7e7e5ab..5d7d807095f1 100644 --- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsDialog.java +++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,43 +22,48 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; +@Deprecated +@SuppressWarnings("UnusedDeclaration") /** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Oct 21, 2003 - * Time: 4:35:44 PM - * To change this template use Options | File Templates. + * @deprecated Use {@link com.intellij.util.net.HttpConfigurable#editConfigurable(javax.swing.JComponent)} + * to remove in IDEA 15 */ public class HTTPProxySettingsDialog extends DialogWrapper { - private final HTTPProxySettingsPanel panel; + private final HttpProxySettingsUi panel; private final Action okAction; private final Action cancelAction; public HTTPProxySettingsDialog() { super(false); + setTitle(CommonBundle.message("title.http.proxy.settings")); - panel = new HTTPProxySettingsPanel(HttpConfigurable.getInstance()); - panel.reset(); + final HttpConfigurable settings = HttpConfigurable.getInstance(); + panel = new HttpProxySettingsUi(settings); + panel.reset(settings); okAction = new AbstractAction(CommonBundle.getOkButtonText()) { - public void actionPerformed(ActionEvent e) { - panel.apply(); + @Override + public void actionPerformed(@NotNull ActionEvent e) { + panel.apply(settings); close(OK_EXIT_CODE); } }; okAction.putValue(DEFAULT_ACTION, Boolean.TRUE.toString()); cancelAction = new AbstractAction(CommonBundle.getCancelButtonText()) { - public void actionPerformed(ActionEvent e) { + @Override + public void actionPerformed(@NotNull ActionEvent e) { close(CANCEL_EXIT_CODE); } }; init(); } + @Override protected JComponent createCenterPanel() { - return panel.createComponent(); + return panel.getComponent(); } + @Override @NotNull protected Action[] createActions() { return new Action[]{okAction, cancelAction}; diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java index 46ea422a3f69..f53c88f372e5 100644 --- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java +++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.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,389 +15,18 @@ */ package com.intellij.util.net; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.ui.MultiLineLabelUI; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.ui.components.JBLabel; -import com.intellij.ui.components.JBRadioButton; -import com.intellij.util.proxy.CommonProxy; -import com.intellij.util.proxy.JavaProxyProperty; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.concurrent.atomic.AtomicReference; - +@SuppressWarnings("UnusedDeclaration") +@Deprecated /** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Aug 28, 2003 - * Time: 3:52:47 PM - * To change this template use Options | File Templates. + * @deprecated Use {@link HttpProxyConfigurable} + * to remove in IDEA 15 */ -public class HTTPProxySettingsPanel implements SearchableConfigurable, Configurable.NoScroll { +public class HTTPProxySettingsPanel extends HttpProxyConfigurable { public static final String NAME = "Proxy"; - private JPanel myMainPanel; - - private JTextField myProxyLoginTextField; - private JPasswordField myProxyPasswordTextField; - private JCheckBox myProxyAuthCheckBox; - private JTextField myProxyPortTextField; - private JTextField myProxyHostTextField; - private JCheckBox myRememberProxyPasswordCheckBox; - - private JLabel myProxyLoginLabel; - private JLabel myProxyPasswordLabel; - private JLabel myHostNameLabel; - private JLabel myPortNumberLabel; - private JBRadioButton myAutoDetectProxyRb; - private JBRadioButton myUseHTTPProxyRb; - private JBLabel mySystemProxyDefined; - private JBRadioButton myNoProxyRb; - private JBRadioButton myHTTP; - private JBRadioButton mySocks; - private JButton myClearPasswordsButton; - private JLabel myErrorLabel; - private JButton myCheckButton; - private JBLabel myOtherWarning; - private JLabel myProxyExceptionsLabel; - private JTextArea myProxyExceptions; - private JLabel myNoProxyForLabel; - private JCheckBox myPacUrlCheckBox; - private JTextField myPacUrlTextField; - private final HttpConfigurable myHttpConfigurable; - private volatile boolean myConnectionCheckInProgress; - - public boolean isModified() { - boolean isModified = false; - HttpConfigurable httpConfigurable = myHttpConfigurable; - if (! Comparing.equal(myProxyExceptions.getText().trim(), httpConfigurable.PROXY_EXCEPTIONS)) return true; - isModified |= httpConfigurable.USE_PROXY_PAC != myAutoDetectProxyRb.isSelected(); - isModified |= httpConfigurable.USE_PAC_URL != myPacUrlCheckBox.isSelected(); - isModified |= !Comparing.strEqual(httpConfigurable.PAC_URL, myPacUrlTextField.getText()); - isModified |= httpConfigurable.USE_HTTP_PROXY != myUseHTTPProxyRb.isSelected(); - isModified |= httpConfigurable.PROXY_AUTHENTICATION != myProxyAuthCheckBox.isSelected(); - isModified |= httpConfigurable.KEEP_PROXY_PASSWORD != myRememberProxyPasswordCheckBox.isSelected(); - isModified |= httpConfigurable.PROXY_TYPE_IS_SOCKS != mySocks.isSelected(); - - isModified |= !Comparing.strEqual(httpConfigurable.PROXY_LOGIN, myProxyLoginTextField.getText()); - isModified |= !Comparing.strEqual(httpConfigurable.getPlainProxyPassword(),new String (myProxyPasswordTextField.getPassword())); - - try { - isModified |= httpConfigurable.PROXY_PORT != Integer.valueOf(myProxyPortTextField.getText()).intValue(); - } catch (NumberFormatException e) { - isModified = true; - } - isModified |= !Comparing.strEqual(httpConfigurable.PROXY_HOST, myProxyHostTextField.getText()); - return isModified; - } - - public HTTPProxySettingsPanel(final HttpConfigurable httpConfigurable) { - final ButtonGroup group = new ButtonGroup(); - group.add(myUseHTTPProxyRb); - group.add(myAutoDetectProxyRb); - group.add(myNoProxyRb); - myNoProxyRb.setSelected(true); - - final ButtonGroup proxyTypeGroup = new ButtonGroup(); - proxyTypeGroup.add(myHTTP); - proxyTypeGroup.add(mySocks); - myHTTP.setSelected(true); - - myProxyExceptions.setBorder(UIUtil.getTextFieldBorder()); - - final Boolean property = Boolean.getBoolean(JavaProxyProperty.USE_SYSTEM_PROXY); - mySystemProxyDefined.setVisible(Boolean.TRUE.equals(property)); - if (Boolean.TRUE.equals(property)) { - mySystemProxyDefined.setIcon(Messages.getWarningIcon()); - mySystemProxyDefined.setFont(mySystemProxyDefined.getFont().deriveFont(Font.BOLD)); - mySystemProxyDefined.setUI(new MultiLineLabelUI()); - } - - myProxyAuthCheckBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - enableProxyAuthentication(myProxyAuthCheckBox.isSelected()); - } - }); - myPacUrlCheckBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - myPacUrlTextField.setEnabled(myPacUrlCheckBox.isSelected()); - } - }); - - final ActionListener listener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - enableProxy(myUseHTTPProxyRb.isSelected()); - } - }; - myUseHTTPProxyRb.addActionListener(listener); - myAutoDetectProxyRb.addActionListener(listener); - myNoProxyRb.addActionListener(listener); - myHttpConfigurable = httpConfigurable; - - myClearPasswordsButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - myHttpConfigurable.clearGenericPasswords(); - Messages.showMessageDialog(myMainPanel, "Proxy passwords were cleared.", "Auto-detected proxy", Messages.getInformationIcon()); - } - }); - - if (HttpConfigurable.getInstance() != null) { - myCheckButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final String title = "Check Proxy Settings"; - final String answer = Messages - .showInputDialog(myMainPanel, "Warning: your settings will be saved.\n\nEnter any URL to check connection to:", - title, Messages.getQuestionIcon(), "http://", null); - if (! StringUtil.isEmptyOrSpaces(answer)) { - apply(); - final HttpConfigurable instance = HttpConfigurable.getInstance(); - final AtomicReference<IOException> exc = new AtomicReference<IOException>(); - myCheckButton.setEnabled(false); - myCheckButton.setText("Check connection (in progress...)"); - myConnectionCheckInProgress = true; - final Application application = ApplicationManager.getApplication(); - application.executeOnPooledThread(new Runnable() { - @Override - public void run() { - HttpURLConnection connection = null; - try { - //already checked for null above - //noinspection ConstantConditions - connection = instance.openHttpConnection(answer); - connection.setReadTimeout(3 * 1000); - connection.setConnectTimeout(3 * 1000); - connection.connect(); - final int code = connection.getResponseCode(); - if (HttpURLConnection.HTTP_OK != code) { - exc.set(new IOException("Error code: " + code)); - } - } - catch (IOException e1) { - exc.set(e1); - } - finally { - if (connection != null) { - connection.disconnect(); - } - } - //noinspection SSBasedInspection - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - myConnectionCheckInProgress = false; - reset(); // since password might have been set - Component parent = null; - if (myMainPanel.isShowing()) { - parent = myMainPanel; - myCheckButton.setText("Check connection"); - myCheckButton.setEnabled(canEnableConnectionCheck()); - } else { - final IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); - if (frame == null) { - return; - } - parent = frame.getComponent(); - } - //noinspection ThrowableResultOfMethodCallIgnored - final IOException exception = exc.get(); - if (exception == null) { - Messages.showMessageDialog(parent, "Connection successful", title, Messages.getInformationIcon()); - } - else { - final String message = exception.getMessage(); - if (instance.USE_HTTP_PROXY) { - instance.LAST_ERROR = message; - } - Messages.showErrorDialog(parent, errorText(message)); - } - } - }); - } - }); - } - } - }); - } else { - myCheckButton.setVisible(false); - } - } - - private boolean canEnableConnectionCheck() { - return ! myNoProxyRb.isSelected() && ! myConnectionCheckInProgress; - } - - public void reset() { - myNoProxyRb.setSelected(true); // default - HttpConfigurable httpConfigurable = myHttpConfigurable; - myAutoDetectProxyRb.setSelected(httpConfigurable.USE_PROXY_PAC); - myPacUrlCheckBox.setSelected(httpConfigurable.USE_PAC_URL); - myPacUrlTextField.setText(httpConfigurable.PAC_URL); - myUseHTTPProxyRb.setSelected(httpConfigurable.USE_HTTP_PROXY); - myProxyAuthCheckBox.setSelected(httpConfigurable.PROXY_AUTHENTICATION); - - enableProxy(httpConfigurable.USE_HTTP_PROXY); - - myProxyLoginTextField.setText(httpConfigurable.PROXY_LOGIN); - myProxyPasswordTextField.setText(httpConfigurable.getPlainProxyPassword()); - - myProxyPortTextField.setText(Integer.toString(httpConfigurable.PROXY_PORT)); - myProxyHostTextField.setText(httpConfigurable.PROXY_HOST); - myProxyExceptions.setText(httpConfigurable.PROXY_EXCEPTIONS); - - myRememberProxyPasswordCheckBox.setSelected(httpConfigurable.KEEP_PROXY_PASSWORD); - mySocks.setSelected(httpConfigurable.PROXY_TYPE_IS_SOCKS); - myHTTP.setSelected(!httpConfigurable.PROXY_TYPE_IS_SOCKS); - - final boolean showError = !StringUtil.isEmptyOrSpaces(httpConfigurable.LAST_ERROR); - myErrorLabel.setVisible(showError); - myErrorLabel.setText(showError ? errorText(httpConfigurable.LAST_ERROR) : ""); - - final String oldStyleText = CommonProxy.getMessageFromProps(CommonProxy.getOldStyleProperties()); - myOtherWarning.setVisible(oldStyleText != null); - if (oldStyleText != null) { - myOtherWarning.setText(oldStyleText); - myOtherWarning.setUI(new MultiLineLabelUI()); - myOtherWarning.setIcon(Messages.getWarningIcon()); - } - } - - private String errorText(final String s) { - return "Problem with connection: " + s; - } - - public void apply () { - HttpConfigurable httpConfigurable = myHttpConfigurable; - if (isModified()){ - httpConfigurable.AUTHENTICATION_CANCELLED = false; - } - httpConfigurable.USE_PROXY_PAC = myAutoDetectProxyRb.isSelected(); - httpConfigurable.USE_PAC_URL = myPacUrlCheckBox.isSelected(); - httpConfigurable.PAC_URL = trimFieldText(myPacUrlTextField); - httpConfigurable.USE_HTTP_PROXY = myUseHTTPProxyRb.isSelected(); - httpConfigurable.PROXY_TYPE_IS_SOCKS = mySocks.isSelected(); - httpConfigurable.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected(); - httpConfigurable.KEEP_PROXY_PASSWORD = myRememberProxyPasswordCheckBox.isSelected(); - - httpConfigurable.PROXY_LOGIN = trimFieldText(myProxyLoginTextField); - httpConfigurable.setPlainProxyPassword(new String(myProxyPasswordTextField.getPassword())); - httpConfigurable.PROXY_EXCEPTIONS = myProxyExceptions.getText(); - - try { - httpConfigurable.PROXY_PORT = Integer.valueOf(trimFieldText(myProxyPortTextField)).intValue(); - } catch (NumberFormatException e) { - httpConfigurable.PROXY_PORT = 80; - } - httpConfigurable.PROXY_HOST = trimFieldText(myProxyHostTextField); - } - - private static String trimFieldText(JTextField field) { - String trimmed = field.getText().trim(); - field.setText(trimmed); - return trimmed; - } - - private void enableProxy (boolean enabled) { - myHostNameLabel.setEnabled(enabled); - myPortNumberLabel.setEnabled(enabled); - myProxyHostTextField.setEnabled(enabled); - myProxyPortTextField.setEnabled(enabled); - mySocks.setEnabled(enabled); - myHTTP.setEnabled(enabled); - myProxyExceptions.setEnabled(enabled); - myProxyExceptions.setBackground(myProxyPortTextField.getBackground()); - myProxyExceptionsLabel.setEnabled(enabled); - myNoProxyForLabel.setEnabled(enabled); - - myProxyAuthCheckBox.setEnabled(enabled); - enableProxyAuthentication(enabled && myProxyAuthCheckBox.isSelected()); - myCheckButton.setEnabled(canEnableConnectionCheck()); - - final boolean autoDetectProxy = myAutoDetectProxyRb.isSelected(); - myPacUrlCheckBox.setEnabled(autoDetectProxy); - myClearPasswordsButton.setEnabled(autoDetectProxy); - myPacUrlTextField.setEnabled(autoDetectProxy && myPacUrlCheckBox.isSelected()); - } - - private void enableProxyAuthentication (boolean enabled) { - myProxyPasswordLabel.setEnabled(enabled); - myProxyLoginLabel.setEnabled(enabled); - - myProxyLoginTextField.setEnabled(enabled); - myProxyPasswordTextField.setEnabled(enabled); - - myRememberProxyPasswordCheckBox.setEnabled(enabled); - } - - public JComponent getComponent() { - return myMainPanel; - } - - public JComponent createComponent() { - return myMainPanel; - } - - @NotNull - public String getId() { - return getHelpTopic(); - } - - public Runnable enableSearch(final String option) { - return null; - } - - @Nls - public String getDisplayName() { - return NAME; - } - - public String getHelpTopic() { - return "http.proxy"; - } - - public void addActionListener(final ActionListener actionListener) { - myProxyLoginTextField.addActionListener(actionListener); - DocumentListener docListener = new DocumentListener() { - public void insertUpdate(DocumentEvent e) { - actionListener.actionPerformed(null); - } - - public void removeUpdate(DocumentEvent e) { - actionListener.actionPerformed(null); - } - - public void changedUpdate(DocumentEvent e) { - actionListener.actionPerformed(null); - } - }; - myProxyPasswordTextField.getDocument().addDocumentListener(docListener); - myProxyAuthCheckBox.addActionListener(actionListener); - myProxyPortTextField.getDocument().addDocumentListener(docListener); - myProxyHostTextField.getDocument().addDocumentListener(docListener); - myUseHTTPProxyRb.addActionListener(actionListener); - myRememberProxyPasswordCheckBox.addActionListener(actionListener); - - } - @Override - public void disposeUIResources() { + public HTTPProxySettingsPanel(@NotNull HttpConfigurable settings) { + super(settings); } -} +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java index d51891a8ffe4..0f9855001b63 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java @@ -21,22 +21,28 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; +import com.intellij.util.Base64; import com.intellij.util.SystemProperties; import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.proxy.CommonProxy; import com.intellij.util.proxy.JavaProxyProperty; import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.annotations.Transient; -import org.apache.commons.codec.binary.Base64; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import gnu.trove.TObjectObjectProcedure; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,75 +54,74 @@ import java.lang.reflect.InvocationTargetException; import java.net.*; import java.util.*; -/** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Oct 7, 2003 - * Time: 3:58:23 PM - * To change this template use Options | File Templates. - */ @State( name = "HttpConfigurable", storages = { - @Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml" ), - @Storage( file = StoragePathMacros.APP_CONFIG + "/proxy.settings.xml" ) + // we use two storages due to backward compatibility, see http://crucible.labs.intellij.net/cru/CR-IC-5142 + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/proxy.settings.xml") }, storageChooser = HttpConfigurable.StorageChooser.class ) -public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent, - ExportableApplicationComponent { +public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ExportableApplicationComponent { public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("idea.connection.timeout", 10000); - private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable"); - public boolean PROXY_TYPE_IS_SOCKS = false; - public boolean USE_HTTP_PROXY = false; - public boolean USE_PROXY_PAC = false; - public volatile transient boolean AUTHENTICATION_CANCELLED = false; - public String PROXY_HOST = ""; + private static final Logger LOG = Logger.getInstance(HttpConfigurable.class); + + public boolean PROXY_TYPE_IS_SOCKS; + public boolean USE_HTTP_PROXY; + public boolean USE_PROXY_PAC; + public volatile transient boolean AUTHENTICATION_CANCELLED; + public String PROXY_HOST; public int PROXY_PORT = 80; - public volatile boolean PROXY_AUTHENTICATION = false; - public volatile String PROXY_LOGIN = ""; - public volatile String PROXY_PASSWORD_CRYPT = ""; - public boolean KEEP_PROXY_PASSWORD = false; + public volatile boolean PROXY_AUTHENTICATION; + public volatile String PROXY_LOGIN; + public volatile String PROXY_PASSWORD_CRYPT; + public boolean KEEP_PROXY_PASSWORD; public transient String LAST_ERROR; - public Map<CommonProxy.HostInfo, ProxyInfo> myGenericPasswords = new HashMap<CommonProxy.HostInfo, ProxyInfo>(); - public Set<CommonProxy.HostInfo> myGenericCancelled = new HashSet<CommonProxy.HostInfo>(); + + private final THashMap<CommonProxy.HostInfo, ProxyInfo> myGenericPasswords = new THashMap<CommonProxy.HostInfo, ProxyInfo>(); + private final Set<CommonProxy.HostInfo> myGenericCancelled = new THashSet<CommonProxy.HostInfo>(); + + public String PROXY_EXCEPTIONS; + public boolean USE_PAC_URL; + public String PAC_URL; + + private transient IdeaWideProxySelector mySelector; + private transient final Object myLock = new Object(); - private IdeaWideProxySelector mySelector; - private IdeaWideAuthenticator myAuthenticator; + + @SuppressWarnings("UnusedDeclaration") public transient Getter<PasswordAuthentication> myTestAuthRunnable = new StaticGetter<PasswordAuthentication>(null); public transient Getter<PasswordAuthentication> myTestGenericAuthRunnable = new StaticGetter<PasswordAuthentication>(null); - public String PROXY_EXCEPTIONS = ""; - public boolean USE_PAC_URL = false; - public String PAC_URL = ""; public static HttpConfigurable getInstance() { return ServiceManager.getService(HttpConfigurable.class); } - public static boolean editConfigurable(final JComponent parent) { - return ShowSettingsUtil.getInstance().editConfigurable(parent, new HTTPProxySettingsPanel(getInstance())); + public static boolean editConfigurable(@Nullable JComponent parent) { + return ShowSettingsUtil.getInstance().editConfigurable(parent, new HttpProxyConfigurable()); } @Override public HttpConfigurable getState() { CommonProxy.isInstalledAssertion(); - final HttpConfigurable state = new HttpConfigurable(); + + HttpConfigurable state = new HttpConfigurable(); XmlSerializerUtil.copyBean(this, state); if (!KEEP_PROXY_PASSWORD) { - state.PROXY_PASSWORD_CRYPT = ""; + state.PROXY_PASSWORD_CRYPT = null; } - correctPasswords(this, state); + correctPasswords(state); return state; } @Override public void initComponent() { mySelector = new IdeaWideProxySelector(this); - myAuthenticator = new IdeaWideAuthenticator(this); - final String name = getClass().getName(); + String name = getClass().getName(); CommonProxy.getInstance().setCustom(name, mySelector); - CommonProxy.getInstance().setCustomAuth(name, myAuthenticator); + CommonProxy.getInstance().setCustomAuth(name, new IdeaWideAuthenticator(this)); } @NotNull @@ -137,62 +142,64 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return getClass().getName(); } - private void correctPasswords(HttpConfigurable from, HttpConfigurable to) { + private void correctPasswords(@NotNull HttpConfigurable to) { synchronized (myLock) { - to.myGenericPasswords = new HashMap<CommonProxy.HostInfo, ProxyInfo>(); - for (Map.Entry<CommonProxy.HostInfo, ProxyInfo> entry : from.myGenericPasswords.entrySet()) { - if (Boolean.TRUE.equals(entry.getValue().isStore())) { - to.myGenericPasswords.put(entry.getKey(), entry.getValue()); + to.myGenericPasswords.retainEntries(new TObjectObjectProcedure<CommonProxy.HostInfo, ProxyInfo>() { + @Override + public boolean execute(CommonProxy.HostInfo hostInfo, ProxyInfo proxyInfo) { + return proxyInfo.isStore(); } - } + }); } } @Override - public void loadState(HttpConfigurable state) { + public void loadState(@NotNull HttpConfigurable state) { XmlSerializerUtil.copyBean(state, this); if (!KEEP_PROXY_PASSWORD) { - PROXY_PASSWORD_CRYPT = ""; + PROXY_PASSWORD_CRYPT = null; } - correctPasswords(state, this); + correctPasswords(this); } - public boolean isGenericPasswordCanceled(final String host, final int port) { + public boolean isGenericPasswordCanceled(@NotNull String host, int port) { synchronized (myLock) { - return myGenericCancelled.contains(Pair.create(host, port)); + return myGenericCancelled.contains(new CommonProxy.HostInfo(null, host, port)); } } public void setGenericPasswordCanceled(final String host, final int port) { synchronized (myLock) { - myGenericCancelled.add(new CommonProxy.HostInfo("", host, port)); + myGenericCancelled.add(new CommonProxy.HostInfo(null, host, port)); } } - public PasswordAuthentication getGenericPassword(final String host, final int port) { + public PasswordAuthentication getGenericPassword(@NotNull String host, int port) { final ProxyInfo proxyInfo; synchronized (myLock) { - proxyInfo = myGenericPasswords.get(new CommonProxy.HostInfo("", host, port)); + proxyInfo = myGenericPasswords.get(new CommonProxy.HostInfo(null, host, port)); + } + if (proxyInfo == null) { + return null; } - if (proxyInfo == null) return null; return new PasswordAuthentication(proxyInfo.getUsername(), decode(String.valueOf(proxyInfo.getPasswordCrypt())).toCharArray()); } - public void putGenericPassword(final String host, final int port, final PasswordAuthentication authentication, final boolean remember) { - final PasswordAuthentication coded = new PasswordAuthentication(authentication.getUserName(), encode(String.valueOf(authentication.getPassword())).toCharArray()); + public void putGenericPassword(final String host, final int port, @NotNull PasswordAuthentication authentication, boolean remember) { + PasswordAuthentication coded = new PasswordAuthentication(authentication.getUserName(), encode(String.valueOf(authentication.getPassword())).toCharArray()); synchronized (myLock) { - myGenericPasswords.put(new CommonProxy.HostInfo("", host, port), new ProxyInfo(remember, coded.getUserName(), String.valueOf( - coded.getPassword()))); + myGenericPasswords.put(new CommonProxy.HostInfo(null, host, port), new ProxyInfo(remember, coded.getUserName(), String.valueOf(coded.getPassword()))); } } @Transient + @Nullable public String getPlainProxyPassword() { - return decode(PROXY_PASSWORD_CRYPT); + return PROXY_PASSWORD_CRYPT == null ? null : decode(PROXY_PASSWORD_CRYPT); } - private String decode(String value) { - return new String(new Base64().decode(value.getBytes())); + private static String decode(String value) { + return new String(Base64.decode(value)); } @Transient @@ -200,42 +207,50 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab PROXY_PASSWORD_CRYPT = encode(password); } - private String encode(String password) { - return new String(new Base64().encode(password.getBytes())); + private static String encode(String password) { + return new String(Base64.encode(password.getBytes(CharsetToolkit.UTF8_CHARSET))); } public PasswordAuthentication getGenericPromptedAuthentication(final String prefix, final String host, final String prompt, final int port, final boolean remember) { if (ApplicationManager.getApplication().isUnitTestMode()) { return myTestGenericAuthRunnable.get(); } - final PasswordAuthentication[] value = new PasswordAuthentication[1]; - final Runnable runnable = new Runnable() { + + final Ref<PasswordAuthentication> value = Ref.create(); + runAboveAll(new Runnable() { + @Override public void run() { - if (isGenericPasswordCanceled(host, port)) return; - final PasswordAuthentication password = getGenericPassword(host, port); + if (isGenericPasswordCanceled(host, port)) { + return; + } + + PasswordAuthentication password = getGenericPassword(host, port); if (password != null) { - value[0] = password; + value.set(password); return; } - final AuthenticationDialog dlg = new AuthenticationDialog(PopupUtil.getActiveComponent(), prefix + host, - "Please enter credentials for: " + prompt, "", "", remember); - dlg.show(); - if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) { - final AuthenticationPanel panel = dlg.getPanel(); - final boolean remember1 = remember && panel.isRememberPassword(); - value[0] = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); - putGenericPassword(host, port, value[0], remember1); - } else { + + AuthenticationDialog dialog = new AuthenticationDialog(PopupUtil.getActiveComponent(), prefix + host, + "Please enter credentials for: " + prompt, "", "", remember); + dialog.show(); + if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + AuthenticationPanel panel = dialog.getPanel(); + PasswordAuthentication passwordAuthentication = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); + putGenericPassword(host, port, passwordAuthentication, remember && panel.isRememberPassword()); + value.set(passwordAuthentication); + } + else { setGenericPasswordCanceled(host, port); } } - }; - runAboveAll(runnable); - return value[0]; + }); + return value.get(); } public PasswordAuthentication getPromptedAuthentication(final String host, final String prompt) { - if (AUTHENTICATION_CANCELLED) return null; + if (AUTHENTICATION_CANCELLED) { + return null; + } final String password = getPlainProxyPassword(); if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password)) { return new PasswordAuthentication(PROXY_LOGIN, password.toCharArray()); @@ -248,63 +263,63 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab if (ApplicationManager.getApplication().isUnitTestMode()) { return myTestGenericAuthRunnable.get(); } - final String login = PROXY_LOGIN == null ? "" : PROXY_LOGIN; final PasswordAuthentication[] value = new PasswordAuthentication[1]; - final Runnable runnable = new Runnable() { + runAboveAll(new Runnable() { + @Override public void run() { - if (AUTHENTICATION_CANCELLED) return; + if (AUTHENTICATION_CANCELLED) { + return; + } + // password might have changed, and the check below is for that - final String password = getPlainProxyPassword(); + String password = getPlainProxyPassword(); if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password)) { value[0] = new PasswordAuthentication(PROXY_LOGIN, password.toCharArray()); return; } - final AuthenticationDialog dlg = new AuthenticationDialog(PopupUtil.getActiveComponent(), "Proxy authentication: " + host, - "Please enter credentials for: " + prompt, login, "", KEEP_PROXY_PASSWORD); - dlg.show(); - if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + AuthenticationDialog dialog = new AuthenticationDialog(PopupUtil.getActiveComponent(), "Proxy authentication: " + host, + "Please enter credentials for: " + prompt, PROXY_LOGIN, "", KEEP_PROXY_PASSWORD); + dialog.show(); + if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { PROXY_AUTHENTICATION = true; - final AuthenticationPanel panel = dlg.getPanel(); + AuthenticationPanel panel = dialog.getPanel(); KEEP_PROXY_PASSWORD = panel.isRememberPassword(); - PROXY_LOGIN = panel.getLogin(); + PROXY_LOGIN = StringUtil.nullize(panel.getLogin()); setPlainProxyPassword(String.valueOf(panel.getPassword())); value[0] = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); } else { AUTHENTICATION_CANCELLED = true; } } - }; - runAboveAll(runnable); + }); return value[0]; } - @SuppressWarnings("MethodMayBeStatic") - private void runAboveAll(final Runnable runnable) { + private static void runAboveAll(@NotNull final Runnable runnable) { final Runnable throughSwing = new Runnable() { @Override public void run() { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); - return; } - try { - SwingUtilities.invokeAndWait(runnable); - } - catch (InterruptedException e) { - LOG.info(e); - } - catch (InvocationTargetException e) { - LOG.info(e); + else { + try { + SwingUtilities.invokeAndWait(runnable); + } + catch (InterruptedException e) { + LOG.info(e); + } + catch (InvocationTargetException e) { + LOG.info(e); + } } } }; - if (ProgressManager.getInstance().getProgressIndicator() != null) { - if (ProgressManager.getInstance().getProgressIndicator().isModal()) { - WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(runnable); - } else { - throughSwing.run(); - } - } else { + ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + if (progressIndicator != null && progressIndicator.isModal()) { + WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(runnable); + } + else { throughSwing.run(); } } @@ -312,22 +327,23 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab //these methods are preserved for compatibility with com.intellij.openapi.project.impl.IdeaServerSettings @Deprecated public void readExternal(Element element) throws InvalidDataException { + //noinspection ConstantConditions loadState(XmlSerializer.deserialize(element, HttpConfigurable.class)); } @Deprecated public void writeExternal(Element element) throws WriteExternalException { XmlSerializer.serializeInto(getState(), element); - if (USE_PROXY_PAC && USE_HTTP_PROXY && ! ApplicationManager.getApplication().isDisposed()) { + if (USE_PROXY_PAC && USE_HTTP_PROXY && !ApplicationManager.getApplication().isDisposed()) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - final IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); + IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); if (frame != null) { USE_PROXY_PAC = false; Messages.showMessageDialog(frame.getComponent(), "Proxy: both 'use proxy' and 'autodetect proxy' settings were set." + "\nOnly one of these options should be selected.\nPlease re-configure.", - "Proxy setup", Messages.getWarningIcon()); + "Proxy Setup", Messages.getWarningIcon()); editConfigurable(frame.getComponent()); } } @@ -344,51 +360,52 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab * @param url URL for HTTP connection * @throws IOException */ - public void prepareURL (String url) throws IOException { - //setAuthenticator(); - CommonProxy.isInstalledAssertion(); - - final URLConnection connection = openConnection(url); + public void prepareURL(@NotNull String url) throws IOException { + URLConnection connection = openConnection(url); try { connection.connect(); connection.getInputStream(); } - catch (Throwable e) { - if (e instanceof IOException) { - throw (IOException)e; - } - } finally { + catch (IOException e) { + throw e; + } + catch (Throwable ignored) { + } + finally { if (connection instanceof HttpURLConnection) { ((HttpURLConnection)connection).disconnect(); } } } + @NotNull public URLConnection openConnection(@NotNull String location) throws IOException { CommonProxy.isInstalledAssertion(); final URL url = new URL(location); URLConnection urlConnection = null; final List<Proxy> proxies = CommonProxy.getInstance().select(url); - if (proxies == null || proxies.isEmpty()) { + if (ContainerUtil.isEmpty(proxies)) { urlConnection = url.openConnection(); - } else { - IOException ioe = null; + } + else { + IOException exception = null; for (Proxy proxy : proxies) { try { urlConnection = url.openConnection(proxy); - } catch (IOException e) { + } + catch (IOException e) { // continue iteration - ioe = e; + exception = e; } } - if (urlConnection == null && ioe != null) { - throw ioe; + if (urlConnection == null && exception != null) { + throw exception; } } - if (urlConnection != null) { - urlConnection.setReadTimeout(CONNECTION_TIMEOUT); - urlConnection.setConnectTimeout(CONNECTION_TIMEOUT); - } + + assert urlConnection != null; + urlConnection.setReadTimeout(CONNECTION_TIMEOUT); + urlConnection.setConnectTimeout(CONNECTION_TIMEOUT); return urlConnection; } @@ -461,12 +478,15 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return result; } - public static boolean isRealProxy(Proxy proxy) { - return ! Proxy.NO_PROXY.equals(proxy) && ! Proxy.Type.DIRECT.equals(proxy.type()); + public static boolean isRealProxy(@NotNull Proxy proxy) { + return !Proxy.NO_PROXY.equals(proxy) && !Proxy.Type.DIRECT.equals(proxy.type()); } + @NotNull public static List<String> convertArguments(@NotNull final List<KeyValue<String, String>> list) { - if (list.isEmpty()) return Collections.emptyList(); + if (list.isEmpty()) { + return Collections.emptyList(); + } final List<String> result = new ArrayList<String>(list.size()); for (KeyValue<String, String> value : list) { result.add("-D" + value.getKey() + "=" + value.getValue()); @@ -481,7 +501,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab } } - public void removeGeneric(CommonProxy.HostInfo info) { + public void removeGeneric(@NotNull CommonProxy.HostInfo info) { synchronized (myLock) { myGenericPasswords.remove(info); } @@ -518,6 +538,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab public String myUsername; public String myPasswordCrypt; + @SuppressWarnings("UnusedDeclaration") public ProxyInfo() { } @@ -547,6 +568,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return myPasswordCrypt; } + @SuppressWarnings("UnusedDeclaration") public void setPasswordCrypt(String passwordCrypt) { myPasswordCrypt = passwordCrypt; } diff --git a/platform/platform-api/src/com/intellij/util/net/HttpProxyConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpProxyConfigurable.java new file mode 100644 index 000000000000..4778c811d63e --- /dev/null +++ b/platform/platform-api/src/com/intellij/util/net/HttpProxyConfigurable.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.net; + +import com.intellij.openapi.options.ConfigurableBase; +import org.jetbrains.annotations.NotNull; + +public class HttpProxyConfigurable extends ConfigurableBase<HttpProxySettingsUi, HttpConfigurable> { + private final HttpConfigurable settings; + + public HttpProxyConfigurable() { + this(HttpConfigurable.getInstance()); + } + + public HttpProxyConfigurable(@NotNull HttpConfigurable settings) { + super("http.proxy", "HTTP Proxy", "http.proxy"); + + this.settings = settings; + } + + @NotNull + @Override + protected HttpConfigurable getSettings() { + return settings; + } + + @Override + protected HttpProxySettingsUi createUi() { + return new HttpProxySettingsUi(settings); + } +}
\ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.form index 5ffe378667d3..3d2ae0575e1f 100644 --- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form +++ b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.form @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> -<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.HTTPProxySettingsPanel"> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.HttpProxySettingsUi"> <grid id="111c4" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="11" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <xy x="111" y="44" width="1040" height="521"/> + <xy x="111" y="44" width="1369" height="608"/> </constraints> <properties/> <border type="none"/> <children> - <grid id="fe3b6" layout-manager="GridLayoutManager" row-count="8" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="fe3b6" layout-manager="GridLayoutManager" row-count="8" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="5" left="20" bottom="10" right="10"/> <constraints> <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/> @@ -34,19 +34,9 @@ <text resource-bundle="messages/CommonBundle" key="editbox.port.number"/> </properties> </component> - <component id="2008d" class="javax.swing.JTextField" binding="myProxyHostTextField"> - <constraints> - <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> - <preferred-size width="150" height="-1"/> - </grid> - </constraints> - <properties/> - </component> - <component id="7e62" class="javax.swing.JTextField" binding="myProxyPortTextField"> + <component id="7e62" class="com.intellij.ui.PortField" binding="myProxyPortTextField"> <constraints> - <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> - <preferred-size width="150" height="-1"/> - </grid> + <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> @@ -105,11 +95,6 @@ <text resource-bundle="messages/CommonBundle" key="checkbox.remember.password"/> </properties> </component> - <hspacer id="92b79"> - <constraints> - <grid row="5" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> - </constraints> - </hspacer> <component id="a16e5" class="javax.swing.JTextArea" binding="myProxyExceptions"> <constraints> <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"> @@ -137,6 +122,14 @@ <text resource-bundle="messages/CommonBundle" key="label.proxy.exceptions.text"/> </properties> </component> + <component id="2008d" class="javax.swing.JTextField" binding="myProxyHostTextField"> + <constraints> + <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> + <preferred-size width="150" height="-1"/> + </grid> + </constraints> + <properties/> + </component> </children> </grid> <vspacer id="53d33"> @@ -177,7 +170,7 @@ <text resource-bundle="messages/CommonBundle" key="http.noproxy"/> </properties> </component> - <grid id="1bb9b" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="1bb9b" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> @@ -193,11 +186,6 @@ <text resource-bundle="messages/CommonBundle" key="http.proxy.type"/> </properties> </component> - <hspacer id="14ffd"> - <constraints> - <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> - </constraints> - </hspacer> <component id="2538c" class="com.intellij.ui.components.JBRadioButton" binding="mySocks"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/> @@ -230,7 +218,7 @@ </constraints> <properties/> </component> - <grid id="fee34" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="fee34" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/> @@ -262,11 +250,6 @@ </constraints> <properties/> </component> - <hspacer id="21dc"> - <constraints> - <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> - </constraints> - </hspacer> </children> </grid> </children> diff --git a/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java new file mode 100644 index 000000000000..e71d8e5af4ec --- /dev/null +++ b/platform/platform-api/src/com/intellij/util/net/HttpProxySettingsUi.java @@ -0,0 +1,386 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.net; + +import com.google.common.net.HostAndPort; +import com.google.common.net.InetAddresses; +import com.google.common.net.InternetDomainName; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.options.ConfigurableUi; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.MultiLineLabelUI; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.ui.PortField; +import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBRadioButton; +import com.intellij.util.proxy.CommonProxy; +import com.intellij.util.proxy.JavaProxyProperty; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.concurrent.atomic.AtomicReference; + +class HttpProxySettingsUi implements ConfigurableUi<HttpConfigurable> { + private JPanel myMainPanel; + + private JTextField myProxyLoginTextField; + private JPasswordField myProxyPasswordTextField; + private JCheckBox myProxyAuthCheckBox; + private PortField myProxyPortTextField; + private JTextField myProxyHostTextField; + private JCheckBox myRememberProxyPasswordCheckBox; + + private JLabel myProxyLoginLabel; + private JLabel myProxyPasswordLabel; + private JLabel myHostNameLabel; + private JLabel myPortNumberLabel; + private JBRadioButton myAutoDetectProxyRb; + private JBRadioButton myUseHTTPProxyRb; + private JBLabel mySystemProxyDefined; + private JBRadioButton myNoProxyRb; + private JBRadioButton myHTTP; + private JBRadioButton mySocks; + private JButton myClearPasswordsButton; + private JLabel myErrorLabel; + private JButton myCheckButton; + private JBLabel myOtherWarning; + private JLabel myProxyExceptionsLabel; + private JTextArea myProxyExceptions; + private JLabel myNoProxyForLabel; + private JCheckBox myPacUrlCheckBox; + private JTextField myPacUrlTextField; + private volatile boolean myConnectionCheckInProgress; + + @Override + public boolean isModified(@NotNull HttpConfigurable settings) { + if (!isValid()) { + return false; + } + + return !Comparing.strEqual(myProxyExceptions.getText().trim(), settings.PROXY_EXCEPTIONS) || + settings.USE_PROXY_PAC != myAutoDetectProxyRb.isSelected() || + settings.USE_PAC_URL != myPacUrlCheckBox.isSelected() || + !Comparing.strEqual(settings.PAC_URL, myPacUrlTextField.getText()) || + settings.USE_HTTP_PROXY != myUseHTTPProxyRb.isSelected() || + settings.PROXY_AUTHENTICATION != myProxyAuthCheckBox.isSelected() || + settings.KEEP_PROXY_PASSWORD != myRememberProxyPasswordCheckBox.isSelected() || + settings.PROXY_TYPE_IS_SOCKS != mySocks.isSelected() || + !Comparing.strEqual(settings.PROXY_LOGIN, myProxyLoginTextField.getText()) || + !Comparing.strEqual(settings.getPlainProxyPassword(), new String(myProxyPasswordTextField.getPassword())) || + settings.PROXY_PORT != myProxyPortTextField.getNumber() || + !Comparing.strEqual(settings.PROXY_HOST, myProxyHostTextField.getText()); + } + + public HttpProxySettingsUi(@NotNull final HttpConfigurable settings) { + ButtonGroup group = new ButtonGroup(); + group.add(myUseHTTPProxyRb); + group.add(myAutoDetectProxyRb); + group.add(myNoProxyRb); + myNoProxyRb.setSelected(true); + + ButtonGroup proxyTypeGroup = new ButtonGroup(); + proxyTypeGroup.add(myHTTP); + proxyTypeGroup.add(mySocks); + myHTTP.setSelected(true); + + myProxyExceptions.setBorder(UIUtil.getTextFieldBorder()); + + Boolean property = Boolean.getBoolean(JavaProxyProperty.USE_SYSTEM_PROXY); + mySystemProxyDefined.setVisible(Boolean.TRUE.equals(property)); + if (Boolean.TRUE.equals(property)) { + mySystemProxyDefined.setIcon(Messages.getWarningIcon()); + mySystemProxyDefined.setFont(mySystemProxyDefined.getFont().deriveFont(Font.BOLD)); + mySystemProxyDefined.setUI(new MultiLineLabelUI()); + } + + myProxyAuthCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + enableProxyAuthentication(myProxyAuthCheckBox.isSelected()); + } + }); + myPacUrlCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + myPacUrlTextField.setEnabled(myPacUrlCheckBox.isSelected()); + } + }); + + ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + enableProxy(myUseHTTPProxyRb.isSelected()); + } + }; + myUseHTTPProxyRb.addActionListener(listener); + myAutoDetectProxyRb.addActionListener(listener); + myNoProxyRb.addActionListener(listener); + + myClearPasswordsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + settings.clearGenericPasswords(); + //noinspection DialogTitleCapitalization + Messages.showMessageDialog(myMainPanel, "Proxy passwords were cleared.", "Auto-detected Proxy", Messages.getInformationIcon()); + } + }); + + configureCheckButton(); + } + + private void configureCheckButton() { + if (HttpConfigurable.getInstance() == null) { + myCheckButton.setVisible(false); + return; + } + + myCheckButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + final String title = "Check Proxy Settings"; + final String answer = Messages.showInputDialog(myMainPanel, "Warning: your settings will be saved.\n\nEnter any URL to check connection to:", + title, Messages.getQuestionIcon(), "http://", null); + if (StringUtil.isEmptyOrSpaces(answer)) { + return; + } + + final HttpConfigurable settings = HttpConfigurable.getInstance(); + apply(settings); + final AtomicReference<IOException> exceptionReference = new AtomicReference<IOException>(); + myCheckButton.setEnabled(false); + myCheckButton.setText("Check connection (in progress...)"); + myConnectionCheckInProgress = true; + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + HttpURLConnection connection = null; + try { + //already checked for null above + //noinspection ConstantConditions + connection = settings.openHttpConnection(answer); + connection.setReadTimeout(3 * 1000); + connection.setConnectTimeout(3 * 1000); + connection.connect(); + final int code = connection.getResponseCode(); + if (HttpURLConnection.HTTP_OK != code) { + exceptionReference.set(new IOException("Error code: " + code)); + } + } + catch (IOException e) { + exceptionReference.set(e); + } + finally { + if (connection != null) { + connection.disconnect(); + } + } + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + myConnectionCheckInProgress = false; + reset(settings); // since password might have been set + Component parent; + if (myMainPanel.isShowing()) { + parent = myMainPanel; + myCheckButton.setText("Check connection"); + myCheckButton.setEnabled(canEnableConnectionCheck()); + } + else { + IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); + if (frame == null) { + return; + } + parent = frame.getComponent(); + } + //noinspection ThrowableResultOfMethodCallIgnored + final IOException exception = exceptionReference.get(); + if (exception == null) { + Messages.showMessageDialog(parent, "Connection successful", title, Messages.getInformationIcon()); + } + else { + final String message = exception.getMessage(); + if (settings.USE_HTTP_PROXY) { + settings.LAST_ERROR = message; + } + Messages.showErrorDialog(parent, errorText(message)); + } + } + }); + } + }); + } + }); + } + + private boolean canEnableConnectionCheck() { + return !myNoProxyRb.isSelected() && !myConnectionCheckInProgress; + } + + @Override + public void reset(@NotNull HttpConfigurable settings) { + myNoProxyRb.setSelected(true); // default + myAutoDetectProxyRb.setSelected(settings.USE_PROXY_PAC); + myPacUrlCheckBox.setSelected(settings.USE_PAC_URL); + myPacUrlTextField.setText(settings.PAC_URL); + myUseHTTPProxyRb.setSelected(settings.USE_HTTP_PROXY); + myProxyAuthCheckBox.setSelected(settings.PROXY_AUTHENTICATION); + + enableProxy(settings.USE_HTTP_PROXY); + + myProxyLoginTextField.setText(settings.PROXY_LOGIN); + myProxyPasswordTextField.setText(settings.getPlainProxyPassword()); + + myProxyPortTextField.setNumber(settings.PROXY_PORT); + myProxyHostTextField.setText(settings.PROXY_HOST); + myProxyExceptions.setText(StringUtil.notNullize(settings.PROXY_EXCEPTIONS)); + + myRememberProxyPasswordCheckBox.setSelected(settings.KEEP_PROXY_PASSWORD); + mySocks.setSelected(settings.PROXY_TYPE_IS_SOCKS); + myHTTP.setSelected(!settings.PROXY_TYPE_IS_SOCKS); + + boolean showError = !StringUtil.isEmptyOrSpaces(settings.LAST_ERROR); + myErrorLabel.setVisible(showError); + myErrorLabel.setText(showError ? errorText(settings.LAST_ERROR) : null); + + final String oldStyleText = CommonProxy.getMessageFromProps(CommonProxy.getOldStyleProperties()); + myOtherWarning.setVisible(oldStyleText != null); + if (oldStyleText != null) { + myOtherWarning.setText(oldStyleText); + myOtherWarning.setUI(new MultiLineLabelUI()); + myOtherWarning.setIcon(Messages.getWarningIcon()); + } + } + + @NotNull + private static String errorText(@NotNull String s) { + return "Problem with connection: " + s; + } + + private boolean isValid() { + if (myUseHTTPProxyRb.isSelected()) { + String host = getText(myProxyHostTextField); + if (host == null) { + return false; + } + + try { + HostAndPort parsedHost = HostAndPort.fromString(host); + if (parsedHost.hasPort()) { + return false; + } + host = parsedHost.getHostText(); + + try { + InetAddresses.forString(host); + return true; + } + catch (IllegalArgumentException e) { + // it is not an IPv4 or IPv6 literal + } + + InternetDomainName.from(host); + } + catch (IllegalArgumentException e) { + return false; + } + + if (myProxyAuthCheckBox.isSelected()) { + return !StringUtil.isEmptyOrSpaces(myProxyLoginTextField.getText()) && myProxyPasswordTextField.getPassword().length > 0; + } + } + return true; + } + + @Override + public void apply(@NotNull HttpConfigurable settings) { + if (!isValid()) { + return; + } + + if (isModified(settings)) { + settings.AUTHENTICATION_CANCELLED = false; + } + + settings.USE_PROXY_PAC = myAutoDetectProxyRb.isSelected(); + settings.USE_PAC_URL = myPacUrlCheckBox.isSelected(); + settings.PAC_URL = getText(myPacUrlTextField); + settings.USE_HTTP_PROXY = myUseHTTPProxyRb.isSelected(); + settings.PROXY_TYPE_IS_SOCKS = mySocks.isSelected(); + settings.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected(); + settings.KEEP_PROXY_PASSWORD = myRememberProxyPasswordCheckBox.isSelected(); + + settings.PROXY_LOGIN = getText(myProxyLoginTextField); + settings.setPlainProxyPassword(new String(myProxyPasswordTextField.getPassword())); + settings.PROXY_EXCEPTIONS = StringUtil.nullize(myProxyExceptions.getText(), true); + + settings.PROXY_PORT = myProxyPortTextField.getNumber(); + settings.PROXY_HOST = getText(myProxyHostTextField); + } + + @Nullable + private static String getText(@NotNull JTextField field) { + return StringUtil.nullize(field.getText(), true); + } + + private void enableProxy(boolean enabled) { + myHostNameLabel.setEnabled(enabled); + myPortNumberLabel.setEnabled(enabled); + myProxyHostTextField.setEnabled(enabled); + myProxyPortTextField.setEnabled(enabled); + mySocks.setEnabled(enabled); + myHTTP.setEnabled(enabled); + myProxyExceptions.setEnabled(enabled); + myProxyExceptions.setBackground(myProxyPortTextField.getBackground()); + myProxyExceptionsLabel.setEnabled(enabled); + myNoProxyForLabel.setEnabled(enabled); + + myProxyAuthCheckBox.setEnabled(enabled); + enableProxyAuthentication(enabled && myProxyAuthCheckBox.isSelected()); + myCheckButton.setEnabled(canEnableConnectionCheck()); + + final boolean autoDetectProxy = myAutoDetectProxyRb.isSelected(); + myPacUrlCheckBox.setEnabled(autoDetectProxy); + myClearPasswordsButton.setEnabled(autoDetectProxy); + myPacUrlTextField.setEnabled(autoDetectProxy && myPacUrlCheckBox.isSelected()); + } + + private void enableProxyAuthentication(boolean enabled) { + myProxyPasswordLabel.setEnabled(enabled); + myProxyLoginLabel.setEnabled(enabled); + + myProxyLoginTextField.setEnabled(enabled); + myProxyPasswordTextField.setEnabled(enabled); + + myRememberProxyPasswordCheckBox.setEnabled(enabled); + } + + @Override + @NotNull + public JComponent getComponent() { + return myMainPanel; + } +} diff --git a/platform/platform-api/src/com/intellij/util/net/IOExceptionDialog.java b/platform/platform-api/src/com/intellij/util/net/IOExceptionDialog.java index f49eb983c3af..642125b275fa 100644 --- a/platform/platform-api/src/com/intellij/util/net/IOExceptionDialog.java +++ b/platform/platform-api/src/com/intellij/util/net/IOExceptionDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Ref; import com.intellij.ui.GuiUtils; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,16 +29,9 @@ import javax.swing.*; import java.awt.event.ActionEvent; import java.lang.reflect.InvocationTargetException; -/** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Nov 19, 2003 - * Time: 10:04:14 PM - * To change this template use Options | File Templates. - */ public class IOExceptionDialog extends DialogWrapper { private static final Logger LOG = Logger.getInstance(IOExceptionDialog.class); - private JTextArea myErrorLabel; + private final JTextArea myErrorLabel; public IOExceptionDialog(String title, String errorText) { super((Project)null, true); @@ -65,8 +59,8 @@ public class IOExceptionDialog extends DialogWrapper { return new Action[] { new AbstractAction(CommonBundle.message("dialog.ioexception.proxy")) { @Override - public void actionPerformed(ActionEvent e) { - new HTTPProxySettingsDialog().show(); + public void actionPerformed(@NotNull ActionEvent e) { + HttpConfigurable.editConfigurable(ObjectUtils.tryCast(e.getSource(), JComponent.class)); } } }; @@ -79,14 +73,14 @@ public class IOExceptionDialog extends DialogWrapper { public static boolean showErrorDialog(final String title, final String text) { final Ref<Boolean> ok = Ref.create(false); try { - final Runnable doRun = new Runnable() { + GuiUtils.runOrInvokeAndWait(new Runnable() { + @Override public void run() { IOExceptionDialog dialog = new IOExceptionDialog(title, text); dialog.show(); ok.set(dialog.isOK()); } - }; - GuiUtils.runOrInvokeAndWait(doRun); + }); } catch (InterruptedException e) { LOG.info(e); diff --git a/platform/platform-api/src/com/intellij/util/net/IdeaWideAuthenticator.java b/platform/platform-api/src/com/intellij/util/net/IdeaWideAuthenticator.java index fedcb359b03d..b3a8fff57763 100644 --- a/platform/platform-api/src/com/intellij/util/net/IdeaWideAuthenticator.java +++ b/platform/platform-api/src/com/intellij/util/net/IdeaWideAuthenticator.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.util.net; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.proxy.CommonProxy; @@ -23,12 +24,6 @@ import com.intellij.util.proxy.NonStaticAuthenticator; import java.net.Authenticator; import java.net.PasswordAuthentication; -/** - * Created with IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 1/30/13 - * Time: 5:58 PM - */ public class IdeaWideAuthenticator extends NonStaticAuthenticator { private final static Logger LOG = Logger.getInstance("#com.intellij.util.net.IdeaWideAuthenticator"); private final HttpConfigurable myHttpConfigurable; @@ -42,12 +37,14 @@ public class IdeaWideAuthenticator extends NonStaticAuthenticator { final String host = CommonProxy.getHostNameReliably(getRequestingHost(), getRequestingSite(), getRequestingURL()); final boolean isProxy = Authenticator.RequestorType.PROXY.equals(getRequestorType()); final String prefix = isProxy ? "Proxy authentication: " : "Server authentication: "; + Application application = ApplicationManager.getApplication(); if (isProxy) { // according to idea-wide settings if (myHttpConfigurable.USE_HTTP_PROXY) { LOG.debug("CommonAuthenticator.getPasswordAuthentication will return common defined proxy"); return myHttpConfigurable.getPromptedAuthentication(host + ":" + getRequestingPort(), getRequestingPrompt()); - } else if (myHttpConfigurable.USE_PROXY_PAC) { + } + else if (myHttpConfigurable.USE_PROXY_PAC) { LOG.debug("CommonAuthenticator.getPasswordAuthentication will return autodetected proxy"); if (myHttpConfigurable.isGenericPasswordCanceled(host, getRequestingPort())) return null; // same but without remembering the results.. @@ -56,16 +53,19 @@ public class IdeaWideAuthenticator extends NonStaticAuthenticator { return password; } // do not try to show any dialogs if application is exiting - if (ApplicationManager.getApplication() == null || ApplicationManager.getApplication().isDisposeInProgress() || - ApplicationManager.getApplication().isDisposed()) return null; + if (application == null || application.isDisposeInProgress() || + application.isDisposed()) { + return null; + } return myHttpConfigurable.getGenericPromptedAuthentication(prefix, host, getRequestingPrompt(), getRequestingPort(), true); } } // do not try to show any dialogs if application is exiting - if (ApplicationManager.getApplication() == null || ApplicationManager.getApplication().isDisposeInProgress() || - ApplicationManager.getApplication().isDisposed()) return null; + if (application == null || application.isDisposeInProgress() || application.isDisposed()) { + return null; + } LOG.debug("CommonAuthenticator.getPasswordAuthentication generic authentication will be asked"); //return myHttpConfigurable.getGenericPromptedAuthentication(prefix, host, getRequestingPrompt(), getRequestingPort(), false); diff --git a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java index df986ea946c4..62199b335425 100644 --- a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java +++ b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java @@ -17,7 +17,6 @@ package com.intellij.util.net; import com.btr.proxy.search.ProxySearch; import com.btr.proxy.selector.pac.PacProxySelector; -import com.btr.proxy.selector.pac.PacScriptSource; import com.btr.proxy.selector.pac.UrlPacScriptSource; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; @@ -77,8 +76,7 @@ public class IdeaWideProxySelector extends ProxySelector { if (myHttpConfigurable.USE_PROXY_PAC) { ProxySelector pacProxySelector = myPacProxySelector.get(); if (myHttpConfigurable.USE_PAC_URL && !StringUtil.isEmpty(myHttpConfigurable.PAC_URL)) { - PacScriptSource pacSource = new UrlPacScriptSource(myHttpConfigurable.PAC_URL); - myPacProxySelector.set(new PacProxySelector(pacSource)); + myPacProxySelector.set(new PacProxySelector(new UrlPacScriptSource(myHttpConfigurable.PAC_URL))); } else if (pacProxySelector == null) { ProxySearch proxySearch = ProxySearch.getDefaultProxySearch(); diff --git a/platform/platform-api/src/com/intellij/util/net/NetUtils.java b/platform/platform-api/src/com/intellij/util/net/NetUtils.java index eb56e08e4d64..b01d4db1f1cb 100644 --- a/platform/platform-api/src/com/intellij/util/net/NetUtils.java +++ b/platform/platform-api/src/com/intellij/util/net/NetUtils.java @@ -66,7 +66,7 @@ public class NetUtils { } public static boolean isLocalhost(@NotNull String host) { - return host.equalsIgnoreCase("localhost") || host.equals("127.0.0.1"); + return host.equalsIgnoreCase("localhost") || host.equals("127.0.0.1") || host.equals("::1"); } private static boolean canBindToLocalSocket(String host, int port) { diff --git a/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java b/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java index eff28a5fbd1e..4aa63cd39f01 100644 --- a/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java +++ b/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.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,8 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.net.NetUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,12 +33,6 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -/** - * Created with IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 1/21/13 - * Time: 12:39 PM - */ public class CommonProxy extends ProxySelector { private final static CommonProxy ourInstance = new CommonProxy(); private final CommonAuthenticator myAuthenticator; @@ -212,14 +208,12 @@ public class CommonProxy extends ProxySelector { } try { ourReenterDefence.set(Boolean.TRUE); - final String host = uri.getHost() == null ? "" : uri.getHost(); - final int port = correctPortByProtocol(uri); - final String protocol = uri.getScheme(); - if ("localhost".equals(host) || "127.0.0.1".equals(host) || "::1".equals(host)) { + String host = StringUtil.notNullize(uri.getHost()); + if (NetUtils.isLocalhost(host)) { return NO_PROXY_LIST; } - final HostInfo info = new HostInfo(protocol, host, port); + final HostInfo info = new HostInfo(uri.getScheme(), host, correctPortByProtocol(uri)); final Map<String, ProxySelector> copy; synchronized (myLock) { if (myNoProxy.contains(Pair.create(info, Thread.currentThread()))) { @@ -230,18 +224,19 @@ public class CommonProxy extends ProxySelector { } for (Map.Entry<String, ProxySelector> entry : copy.entrySet()) { final List<Proxy> proxies = entry.getValue().select(uri); - if (proxies != null && proxies.size() > 0) { + if (!ContainerUtil.isEmpty(proxies)) { LOG.debug("CommonProxy.select returns custom proxy for " + uri.toString() + ", " + proxies.toString()); return proxies; } } return NO_PROXY_LIST; - } finally { + } + finally { ourReenterDefence.remove(); } } - private int correctPortByProtocol(@NotNull URI uri) { + private static int correctPortByProtocol(@NotNull URI uri) { if (uri.getPort() == -1) { if ("http".equals(uri.getScheme())) { return ProtocolDefaultPorts.HTTP; @@ -330,7 +325,8 @@ public class CommonProxy extends ProxySelector { if (host == null) { if (site != null) { host = site.getHostName(); - } else if (requestingUrl != null) { + } + else if (requestingUrl != null) { host = requestingUrl.getHost(); } } @@ -351,7 +347,7 @@ public class CommonProxy extends ProxySelector { public HostInfo() { } - public HostInfo(String protocol, @NotNull String host, int port) { + public HostInfo(@Nullable String protocol, @NotNull String host, int port) { myPort = port; myHost = host; myProtocol = protocol; @@ -371,16 +367,15 @@ public class CommonProxy extends ProxySelector { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } HostInfo info = (HostInfo)o; - - if (myPort != info.myPort) return false; - if (!myHost.equals(info.myHost)) return false; - if (myProtocol != null ? !myProtocol.equals(info.myProtocol) : info.myProtocol != null) return false; - - return true; + return myPort == info.myPort && myHost.equals(info.myHost) && Comparing.equal(myProtocol, info.myProtocol); } @Override diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index d73e21e8dc3a..b11ca7f3222f 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -223,10 +223,10 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { } public int getDecrementButtonHeight() { - return decrButton.getHeight(); + return Math.max(0, decrButton.getHeight()); } public int getIncrementButtonHeight() { - return incrButton.getHeight(); + return Math.max(0, incrButton.getHeight()); } private void resetRegularThumbAnimator() { @@ -276,6 +276,16 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { return new ButtonlessScrollBarUI(); } + + public static BasicScrollBarUI createTransparent() { + return new ButtonlessScrollBarUI() { + @Override + public boolean alwaysShowTrack() { + return false; + } + }; + } + @Override public void installUI(JComponent c) { super.installUI(c); diff --git a/platform/platform-api/src/com/intellij/util/ui/StatusText.java b/platform/platform-api/src/com/intellij/util/ui/StatusText.java index 60f8c5c6cbc1..479b968d4317 100644 --- a/platform/platform-api/src/com/intellij/util/ui/StatusText.java +++ b/platform/platform-api/src/com/intellij/util/ui/StatusText.java @@ -186,7 +186,8 @@ public abstract class StatusText { } public void paint(Component owner, Graphics g) { - if (!isStatusVisible() || owner != myOwner) return; + boolean wrongComponent = owner != myOwner && owner != null && owner.getParent() != myOwner; + if (!isStatusVisible() || wrongComponent) return; Rectangle b = getTextComponentBound(); myComponent.setBounds(0, 0, b.width, b.height); |