From 81c40c864dfe19f146337a6937e632c429b618e8 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 23 Sep 2016 15:26:50 +0300 Subject: [PATCH 01/39] HTMLEditorKitProvider extracted to make initialization lazy --- .../util/ui/HTMLEditorKitProvider.java | 83 +++++++++++++++++++ .../util/src/com/intellij/util/ui/UIUtil.java | 46 +--------- 2 files changed, 84 insertions(+), 45 deletions(-) create mode 100644 platform/util/src/com/intellij/util/ui/HTMLEditorKitProvider.java diff --git a/platform/util/src/com/intellij/util/ui/HTMLEditorKitProvider.java b/platform/util/src/com/intellij/util/ui/HTMLEditorKitProvider.java new file mode 100644 index 000000000000..dc117df42315 --- /dev/null +++ b/platform/util/src/com/intellij/util/ui/HTMLEditorKitProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.ui; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.util.ui.accessibility.ScreenReader; +import org.jetbrains.annotations.NonNls; + +import javax.swing.*; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; +import java.awt.*; + +import static com.intellij.util.ui.UIUtil.getLabelFont; +import static com.intellij.util.ui.UIUtil.isUnderDarcula; + +/** + * @author Dmitry Avdeev + */ +public class HTMLEditorKitProvider { + private static final Logger LOG = Logger.getInstance(HTMLEditorKitProvider.class); + private static final StyleSheet DEFAULT_HTML_KIT_CSS; + + static { + blockATKWrapper(); + // save the default JRE CSS and .. + HTMLEditorKit kit = new HTMLEditorKit(); + DEFAULT_HTML_KIT_CSS = kit.getStyleSheet(); + // .. erase global ref to this CSS so no one can alter it + kit.setStyleSheet(null); + } + + private static void blockATKWrapper() { + /* + * The method should be called before java.awt.Toolkit.initAssistiveTechnologies() + * which is called from Toolkit.getDefaultToolkit(). + */ + if (!(SystemInfo.isLinux && Registry.is("linux.jdk.accessibility.atkwrapper.block"))) return; + + if (ScreenReader.isEnabled(ScreenReader.ATK_WRAPPER)) { + // Replace AtkWrapper with a dummy Object. It'll be instantiated & GC'ed right away, a NOP. + System.setProperty("javax.accessibility.assistive_technologies", "java.lang.Object"); + LOG.info(ScreenReader.ATK_WRAPPER + " is blocked, see IDEA-149219"); + } + } + + public static HTMLEditorKit getHTMLEditorKit(boolean noGapsBetweenParagraphs) { + Font font = getLabelFont(); + @NonNls String family = !SystemInfo.isWindows && font != null ? font.getFamily() : "Tahoma"; + int size = font != null ? font.getSize() : JBUI.scale(11); + + String customCss = String.format("body, div, p { font-family: %s; font-size: %s; }", family, size); + if (noGapsBetweenParagraphs) { + customCss += " p { margin-top: 0; }"; + } + + final StyleSheet style = new StyleSheet(); + style.addStyleSheet(isUnderDarcula() ? (StyleSheet)UIManager.getDefaults().get("StyledEditorKit.JBDefaultStyle") : DEFAULT_HTML_KIT_CSS); + style.addRule(customCss); + + return new HTMLEditorKit() { + @Override + public StyleSheet getStyleSheet() { + return style; + } + }; + } +} diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index fad7a812e93c..a518786d789c 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -30,7 +30,6 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import com.intellij.util.containers.JBTreeTraverser; import com.intellij.util.containers.WeakHashMap; -import com.intellij.util.ui.accessibility.ScreenReader; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -93,31 +92,6 @@ public class UIUtil { public static final String BORDER_LINE = "
"; - private static final StyleSheet DEFAULT_HTML_KIT_CSS; - - static { - blockATKWrapper(); - // save the default JRE CSS and .. - HTMLEditorKit kit = new HTMLEditorKit(); - DEFAULT_HTML_KIT_CSS = kit.getStyleSheet(); - // .. erase global ref to this CSS so no one can alter it - kit.setStyleSheet(null); - } - - private static void blockATKWrapper() { - /* - * The method should be called before java.awt.Toolkit.initAssistiveTechnologies() - * which is called from Toolkit.getDefaultToolkit(). - */ - if (!(SystemInfo.isLinux && Registry.is("linux.jdk.accessibility.atkwrapper.block"))) return; - - if (ScreenReader.isEnabled(ScreenReader.ATK_WRAPPER)) { - // Replace AtkWrapper with a dummy Object. It'll be instantiated & GC'ed right away, a NOP. - System.setProperty("javax.accessibility.assistive_technologies", "java.lang.Object"); - LOG.info(ScreenReader.ATK_WRAPPER + " is blocked, see IDEA-149219"); - } - } - public static int getMultiClickInterval() { Object property = Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval"); if (property instanceof Integer) { @@ -2335,25 +2309,7 @@ public class UIUtil { } public static HTMLEditorKit getHTMLEditorKit(boolean noGapsBetweenParagraphs) { - Font font = getLabelFont(); - @NonNls String family = !SystemInfo.isWindows && font != null ? font.getFamily() : "Tahoma"; - int size = font != null ? font.getSize() : JBUI.scale(11); - - String customCss = String.format("body, div, p { font-family: %s; font-size: %s; }", family, size); - if (noGapsBetweenParagraphs) { - customCss += " p { margin-top: 0; }"; - } - - final StyleSheet style = new StyleSheet(); - style.addStyleSheet(isUnderDarcula() ? (StyleSheet)UIManager.getDefaults().get("StyledEditorKit.JBDefaultStyle") : DEFAULT_HTML_KIT_CSS); - style.addRule(customCss); - - return new HTMLEditorKit() { - @Override - public StyleSheet getStyleSheet() { - return style; - } - }; + return HTMLEditorKitProvider.getHTMLEditorKit(noGapsBetweenParagraphs); } public static void removeScrollBorder(final Component c) { From 2ea08c9bad1448493d6cd46492673e013deb2fd1 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 23 Sep 2016 15:37:22 +0300 Subject: [PATCH 02/39] lazy diff view initialization --- .../openapi/util/NotNullLazyValue.java | 4 +++ .../vcs/changes/ChangesViewManager.java | 27 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java index f08475ce3d90..8cab38c39fb6 100644 --- a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java +++ b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java @@ -44,6 +44,10 @@ public abstract class NotNullLazyValue { return result; } + public boolean isComputed() { + return myValue != null; + } + @NotNull public static NotNullLazyValue createConstantValue(@NotNull final T value) { return new NotNullLazyValue() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java index ec4409176f40..e011b1b328db 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java @@ -34,9 +34,7 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Factory; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsBundle; @@ -97,7 +95,13 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi private JBSplitter mySplitter; private boolean myDetailsOn; - @NotNull private final MyChangeProcessor myDiffDetails; + @NotNull private final NotNullLazyValue myDiffDetails = new NotNullLazyValue() { + @NotNull + @Override + protected MyChangeProcessor compute() { + return new MyChangeProcessor(myProject); + } + }; @NotNull private final TreeSelectionListener myTsl; private Content myContent; @@ -112,7 +116,6 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi myContentManager = contentManager; myView = new ChangesListView(project); myRepaintAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project); - myDiffDetails = new MyChangeProcessor(myProject); myTsl = new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { @@ -167,7 +170,6 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi } public void projectClosed() { - Disposer.dispose(myDiffDetails); myView.removeTreeSelectionListener(myTsl); myDisposed = true; myRepaintAlarm.cancelAllRequests(); @@ -239,17 +241,19 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi private void changeDetails() { if (!myDetailsOn) { - myDiffDetails.clear(); + if (myDiffDetails.isComputed()) { + myDiffDetails.getValue().clear(); - if (mySplitter.getSecondComponent() != null) { - setChangeDetailsPanel(null); + if (mySplitter.getSecondComponent() != null) { + setChangeDetailsPanel(null); + } } } else { - myDiffDetails.refresh(); + myDiffDetails.getValue().refresh(); if (mySplitter.getSecondComponent() == null) { - setChangeDetailsPanel(myDiffDetails.getComponent()); + setChangeDetailsPanel(myDiffDetails.getValue().getComponent()); } } } @@ -528,6 +532,7 @@ public class ChangesViewManager implements ChangesViewI, ProjectComponent, Persi private class MyChangeProcessor extends CacheChangeProcessor { public MyChangeProcessor(@NotNull Project project) { super(project, DiffPlaces.CHANGES_VIEW); + Disposer.register(project, this); } @Override From ce61fac03d8118b680d0f85e8adb992b0b6ff411 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 23 Sep 2016 15:56:41 +0300 Subject: [PATCH 03/39] Fix import error after refactoring --- python/helpers/pydev/_pydev_bundle/_pydev_completer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/_pydev_completer.py b/python/helpers/pydev/_pydev_bundle/_pydev_completer.py index 380cd3aeef49..d1c10b5ecb8f 100644 --- a/python/helpers/pydev/_pydev_bundle/_pydev_completer.py +++ b/python/helpers/pydev/_pydev_bundle/_pydev_completer.py @@ -20,7 +20,7 @@ except ImportError: IS_JYTHON = False from _pydev_bundle import _pydev_imports_tipper -from _pydevd_bundle import pydevd_vars +from _pydevd_bundle import pydevd_xml dir2 = _pydev_imports_tipper.generate_imports_tip_for_module @@ -176,8 +176,8 @@ def generate_completions_as_xml(frame, act_tok): #list(tuple(name, descr, parameters, type)) completions = completer.complete(act_tok) - valid_xml = pydevd_vars.make_valid_xml_value - quote = pydevd_vars.quote + valid_xml = pydevd_xml.make_valid_xml_value + quote = pydevd_xml.quote msg = [""] From 14e56772ba3db0b87e5beaad62be4147cacadd63 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 23 Sep 2016 16:03:16 +0300 Subject: [PATCH 04/39] Collect UI scale statistics --- .../statistic/ScaleInfoUsageCollector.java | 60 +++++++++++++++++++ .../src/META-INF/PlatformExtensions.xml | 1 + .../util/src/com/intellij/util/ui/JBUI.java | 23 +++---- 3 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/internal/statistic/ScaleInfoUsageCollector.java diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ScaleInfoUsageCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/ScaleInfoUsageCollector.java new file mode 100644 index 000000000000..fdec26e5d70a --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/ScaleInfoUsageCollector.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2016 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.internal.statistic; + +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; +import org.jdesktop.swingx.util.OS; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Set; + +/** + * @author tav + */ +public class ScaleInfoUsageCollector extends UsagesCollector { + @NotNull + @Override + public Set getUsages() throws CollectUsagesException { + float scale = JBUI.SYSTEM_DEF_SCALE; + + if (OS.isMacOSX()) { + scale = UIUtil.isRetina() ? 2.0f : 1.0f; + } else { + int scaleBase = (int)Math.floor(scale); + float scaleFract = scale - scaleBase; + + if (scaleFract == 0.0f) scaleFract = 0.0f; // count integer scale on a precise match only + else if (scaleFract < 0.375f) scaleFract = 0.25f; + else if (scaleFract < 0.625f) scaleFract = 0.5f; + else scaleFract = 0.75f; + + scale = scaleBase + scaleFract; + } + + String os = OS.isWindows() ? "Windows" : OS.isLinux() ? "Linux" : OS.isMacOSX() ? "Mac" : "Unknown OS"; + return Collections.singleton(new UsageDescriptor(os + " screen scale " + scale, 1)); + } + + @NotNull + @Override + public GroupDescriptor getGroupId() { + return GroupDescriptor.create("user.jdk"); + } +} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 60eb886c5d45..071385c6b135 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -353,6 +353,7 @@ + diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 5a95162f3aa2..e14f67b8289c 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -37,23 +37,24 @@ import java.awt.*; public class JBUI { private static final Logger LOG = Logger.getInstance("#com.intellij.util.ui.JBUI"); - private static float scaleFactor = 1.0f; + /** + * A default system scale factor. + */ + public static final float SYSTEM_DEF_SCALE = getSystemDefScale(); + + private static float scaleFactor; static { - calculateScaleFactor(); + setScaleFactor(SYSTEM_DEF_SCALE); } - private static void calculateScaleFactor() { + private static float getSystemDefScale() { if (SystemInfo.isMac) { - LOG.info("UI scale factor: 1.0"); - scaleFactor = 1.0f; - return; + return 1.0f; } if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { - LOG.info("UI scale factor: 1.0"); - scaleFactor = 1.0f; - return; + return 1.0f; } UIUtil.initSystemFontData(); @@ -65,11 +66,13 @@ public class JBUI { } else { size = Fonts.label().getSize(); } - setScaleFactor(size/UIUtil.DEF_SYSTEM_FONT_SIZE); + return size / UIUtil.DEF_SYSTEM_FONT_SIZE; } public static void setScaleFactor(float scale) { if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) { + scaleFactor = 1.0f; + LOG.info("UI scale factor: 1.0"); return; } From fc02ead2e8604b60af6c838c309f3df0cfd15636 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 23 Sep 2016 16:13:02 +0300 Subject: [PATCH 05/39] Tests: fix test data after fixing PY-20476 --- python/helpers/pydev/tests_pydevd_python/test_pydev_monkey.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/helpers/pydev/tests_pydevd_python/test_pydev_monkey.py b/python/helpers/pydev/tests_pydevd_python/test_pydev_monkey.py index 27fa4f6b8e5d..67859a226e7a 100644 --- a/python/helpers/pydev/tests_pydevd_python/test_pydev_monkey.py +++ b/python/helpers/pydev/tests_pydevd_python/test_pydev_monkey.py @@ -25,6 +25,7 @@ class TestCase(unittest.TestCase): 'sys.path.append(r\'%s\'); ' 'import pydevd; pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, ' 'trace_only_current_thread=False, patch_multiprocessing=True); ' + 'sys.original_argv = []; ' 'connect("127.0.0.1")' % pydev_src_dir, pydev_monkey.patch_arg_str_win(check) ) @@ -48,6 +49,7 @@ class TestCase(unittest.TestCase): ( 'import sys; sys.path.append(r\'%s\'); import pydevd; ' 'pydevd.settrace(host=\'127.0.0.1\', port=0, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); ' + 'sys.original_argv = []; ' 'connect(\\"127.0.0.1\\")' ) % pydev_src_dir ]) From 02a2126f6aba8f6a874665066ef3cbec77516de4 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 23 Sep 2016 16:34:31 +0300 Subject: [PATCH 06/39] initialize visible toolwindows synchronously --- .../wm/impl/ToolWindowManagerImpl.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 21111bd2504e..edec3ae37125 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -424,12 +424,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void initToolWindow(@NotNull ToolWindowEP bean) { - JLabel label = new JLabel("Initializing...", SwingConstants.CENTER); - label.setOpaque(true); - final Color treeBg = UIManager.getColor("Tree.background"); - label.setBackground(ColorUtil.toAlpha(treeBg, 180)); - final Color treeFg = UIUtil.getTreeForeground(); - label.setForeground(ColorUtil.toAlpha(treeFg, 180)); + WindowInfoImpl before = myLayout.getInfo(bean.id, false); + boolean visible = before != null && before.isVisible(); + JLabel label = createInitializingLabel(); ToolWindowAnchor toolWindowAnchor = ToolWindowAnchor.fromText(bean.anchor); final ToolWindowFactory factory = bean.getToolWindowFactory(); final ToolWindowImpl toolWindow = @@ -461,7 +458,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements toolWindow.ensureContentInitialized(); activation.setDone(); }; - if (ApplicationManager.getApplication().isUnitTestMode()) { + if (visible || ApplicationManager.getApplication().isUnitTestMode()) { runnable.run(); } else { @@ -469,6 +466,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } + @NotNull + private static JLabel createInitializingLabel() { + JLabel label = new JLabel("Initializing...", SwingConstants.CENTER); + label.setOpaque(true); + final Color treeBg = UIManager.getColor("Tree.background"); + label.setBackground(ColorUtil.toAlpha(treeBg, 180)); + final Color treeFg = UIUtil.getTreeForeground(); + label.setForeground(ColorUtil.toAlpha(treeFg, 180)); + return label; + } + @Override public void projectClosed() { final String[] ids = getToolWindowIds(); From 3f6cbd668d81c0df0a76d4cdfb65c88a1eb2dd63 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 23 Sep 2016 12:02:18 +0300 Subject: [PATCH 07/39] IDEA-160533 Add watch edit box is incorrectly placed when watch window is merged with variables - remove name and separator from the inplace editor --- .../impl/ui/tree/SetValueInplaceEditor.java | 22 +++++++++++++++---- .../impl/ui/tree/TreeInplaceEditor.java | 8 +++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java index 038910bdeb2e..0fc445f3436e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.Messages; import com.intellij.ui.AppUIUtil; import com.intellij.ui.SimpleColoredComponent; +import com.intellij.util.ui.JBUI; import com.intellij.xdebugger.frame.XValueModifier; import com.intellij.xdebugger.frame.presentation.XValuePresentation; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; @@ -28,6 +29,7 @@ import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresentationUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -39,24 +41,36 @@ public class SetValueInplaceEditor extends XDebuggerTreeInplaceEditor { private final JPanel myEditorPanel; private final XValueModifier myModifier; private final XValueNodeImpl myValueNode; + private final int myNameOffset; private SetValueInplaceEditor(final XValueNodeImpl node, @NotNull final String nodeName) { super(node, "setValue"); myValueNode = node; myModifier = myValueNode.getValueContainer().getModifier(); - myEditorPanel = new JPanel(); - myEditorPanel.setLayout(new BorderLayout(0, 0)); SimpleColoredComponent nameLabel = new SimpleColoredComponent(); + nameLabel.getIpad().right = 0; + nameLabel.getIpad().left = 0; nameLabel.setIcon(myNode.getIcon()); nameLabel.append(nodeName, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES); XValuePresentation presentation = node.getValuePresentation(); if (presentation != null) { XValuePresentationUtil.appendSeparator(nameLabel, presentation.getSeparator()); } - myEditorPanel.add(nameLabel, BorderLayout.WEST); + myNameOffset = nameLabel.getPreferredSize().width; + myEditorPanel = JBUI.Panels.simplePanel(myExpressionEditor.getComponent()); + } - myEditorPanel.add(myExpressionEditor.getComponent(), BorderLayout.CENTER); + @Nullable + @Override + protected Rectangle getEditorBounds() { + Rectangle bounds = super.getEditorBounds(); + if (bounds == null) { + return null; + } + bounds.x += myNameOffset; + bounds.width -= myNameOffset; + return bounds; } public static void show(final XValueNodeImpl node, @NotNull final String nodeName) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java index d60f5099d46d..a1c0a881de41 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java @@ -97,10 +97,8 @@ public abstract class TreeInplaceEditor implements AWTEventListener { protected abstract Project getProject(); private static void setInplaceEditorBounds(JComponent component, int x, int y, int width, int height) { - int preferredHeight = component.getPreferredSize().height; - int h = Math.max(height, preferredHeight); - int delta = Math.max(0, h - height) / 2; - component.setBounds(x, y - delta, width, Math.max(height, preferredHeight)); + int h = Math.max(height, component.getPreferredSize().height); + component.setBounds(x, y - (h - height) / 2, width, h); } public final void show() { @@ -271,7 +269,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener { } @Nullable - private Rectangle getEditorBounds() { + protected Rectangle getEditorBounds() { final JTree tree = getTree(); Rectangle bounds = tree.getVisibleRect(); Rectangle nodeBounds = tree.getPathBounds(getNodePath()); From 593ce39365f54fafccc5e0c763c8eee4631fb479 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 23 Sep 2016 17:06:19 +0300 Subject: [PATCH 08/39] IDEA-160533 Add watch edit box is incorrectly placed when watch window is merged with variables - moved language selector inside the field and to the right --- .../intellij/ui/ComboboxEditorTextField.java | 8 +- .../impl/ui/XDebuggerEditorBase.java | 33 +++++-- .../impl/ui/XDebuggerExpressionComboBox.java | 96 +++++++++++++------ 3 files changed, 98 insertions(+), 39 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/ComboboxEditorTextField.java b/platform/platform-impl/src/com/intellij/ui/ComboboxEditorTextField.java index 4afe9bdb16d7..79b887ef5bf1 100644 --- a/platform/platform-impl/src/com/intellij/ui/ComboboxEditorTextField.java +++ b/platform/platform-impl/src/com/intellij/ui/ComboboxEditorTextField.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -131,8 +131,10 @@ public class ComboboxEditorTextField extends EditorTextField { // TODO: if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF() || (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel())) { IdeFocusManager.getInstance(getProject()).doWhenFocusSettlesDown(() -> { - final Container parent1 = getParent(); - if (parent1 != null) parent1.repaint(); + JComboBox comboBox = UIUtil.getParentOfType(JComboBox.class, this); + if (comboBox != null) { + comboBox.repaint(); + } }); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java index 5b8982ea6efb..5d36ba5952f8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java @@ -38,6 +38,7 @@ import com.intellij.reference.SoftReference; import com.intellij.ui.ClickListener; import com.intellij.ui.LayeredIcon; import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.components.BorderLayoutPanel; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; @@ -139,22 +140,33 @@ public abstract class XDebuggerEditorBase { } protected JPanel decorate(JComponent component, boolean multiline, boolean showEditor) { - JPanel panel = JBUI.Panels.simplePanel(); + BorderLayoutPanel panel = JBUI.Panels.simplePanel(); JPanel factoryPanel = JBUI.Panels.simplePanel(); factoryPanel.add(myChooseFactory, multiline ? BorderLayout.NORTH : BorderLayout.CENTER); panel.add(factoryPanel, BorderLayout.WEST); if (!multiline && showEditor) { - ComponentWithBrowseButton componentWithButton = - new ComponentWithBrowseButton<>(component, e -> showCodeFragmentEditor(component, this)); - componentWithButton.setButtonIcon(AllIcons.Actions.ShowViewer); - componentWithButton.getButton().setDisabledIcon(IconLoader.getDisabledIcon(AllIcons.Actions.ShowViewer)); - panel.add(componentWithButton, BorderLayout.CENTER); - } else { - panel.add(component, BorderLayout.CENTER); + component = addMultilineButton(component); } + panel.addToCenter(component); + + return panel; + } + + protected JPanel addMultilineButton(JComponent component) { + ComponentWithBrowseButton componentWithButton = + new ComponentWithBrowseButton<>(component, e -> showCodeFragmentEditor(component, this)); + componentWithButton.setButtonIcon(AllIcons.Actions.ShowViewer); + componentWithButton.getButton().setDisabledIcon(IconLoader.getDisabledIcon(AllIcons.Actions.ShowViewer)); + return componentWithButton; + } + + protected JComponent addChooser(JComponent component) { + BorderLayoutPanel panel = JBUI.Panels.simplePanel(component); + panel.setBackground(component.getBackground()); + panel.addToRight(myChooseFactory); return panel; } @@ -345,7 +357,10 @@ public abstract class XDebuggerEditorBase { protected void doOKAction() { super.doOKAction(); baseEditor.setExpression(inputComponent.getInputEditor().getExpression()); - IdeFocusManager.findInstance().requestFocus(baseEditor.getEditorComponent(), false); + JComponent component = baseEditor.getPreferredFocusedComponent(); + if (component != null) { + IdeFocusManager.findInstance().requestFocus(component, false); + } } @Nullable diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java index 0bf83c4d51bd..d5069dbf36fb 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.ui.EditorComboBoxEditor; import com.intellij.ui.EditorComboBoxRenderer; +import com.intellij.ui.EditorTextField; import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.XSourcePosition; @@ -35,6 +36,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionListener; /** * @author nik @@ -42,7 +44,7 @@ import java.awt.*; public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { private final JComponent myComponent; private final ComboBox myComboBox; - private EditorComboBoxEditor myEditor; + private XDebuggerComboBoxEditor myEditor; private XExpression myExpression; public XDebuggerExpressionComboBox(@NotNull Project project, @NotNull XDebuggerEditorsProvider debuggerEditorsProvider, @Nullable @NonNls String historyId, @@ -56,7 +58,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { myComboBox.setMinimumSize(minimumSize); initEditor(); fillComboBox(); - myComponent = decorate(myComboBox, false, showEditor); + myComponent = showEditor ? addMultilineButton(myComboBox) : myComboBox; } public ComboBox getComboBox() { @@ -70,11 +72,11 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { @Nullable public Editor getEditor() { - return myEditor.getEditor(); + return myEditor.getEditorTextField().getEditor(); } public JComponent getEditorComponent() { - return myEditor.getEditorComponent(); + return myEditor.getEditorTextField(); } public void setEnabled(boolean enable) { @@ -92,23 +94,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { } private void initEditor() { - myEditor = new EditorComboBoxEditor(getProject(), getEditorsProvider().getFileType()) { - @Override - public void setItem(Object anObject) { - if (anObject == null) { - anObject = XExpressionImpl.EMPTY_EXPRESSION; - } - XExpression expression = (XExpression)anObject; - getEditorComponent().setNewDocumentAndFileType(getFileType(expression), createDocument(expression)); - } - - @Override - protected void onEditorCreate(EditorEx editor) { - editor.putUserData(DebuggerCopyPastePreprocessor.REMOVE_NEWLINES_ON_PASTE, true); - editor.getColorsScheme().setEditorFontSize(myComboBox.getFont().getSize()); - } - }; - myEditor.getEditorComponent().setFontInheritedFromLAF(false); + myEditor = new XDebuggerComboBoxEditor(); myComboBox.setEditor(myEditor); //myEditor.setItem(myExpression); myComboBox.setRenderer(new EditorComboBoxRenderer(myEditor)); @@ -144,20 +130,76 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { @Override public XExpression getExpression() { - Object document = myEditor.getItem(); - if (document instanceof Document) { // sometimes null on Mac - return getEditorsProvider().createExpression(getProject(), (Document)document, myExpression.getLanguage(), myExpression.getMode()); - } - return myExpression; + XExpression item = myEditor.getItem(); + return item != null ? item : myExpression; } @Override public JComponent getPreferredFocusedComponent() { - return (JComponent)myComboBox.getEditor().getEditorComponent(); + return myEditor.getEditorTextField(); } @Override public void selectAll() { myComboBox.getEditor().selectAll(); } + + private class XDebuggerComboBoxEditor implements ComboBoxEditor { + private final JComponent myPanel; + private final EditorComboBoxEditor myDelegate; + + public XDebuggerComboBoxEditor() { + myDelegate = new EditorComboBoxEditor(getProject(), getEditorsProvider().getFileType()) { + @Override + protected void onEditorCreate(EditorEx editor) { + editor.putUserData(DebuggerCopyPastePreprocessor.REMOVE_NEWLINES_ON_PASTE, true); + editor.getColorsScheme().setEditorFontSize(myComboBox.getFont().getSize()); + } + }; + myDelegate.getEditorComponent().setFontInheritedFromLAF(false); + myPanel = addChooser(myDelegate.getEditorComponent()); + } + + public EditorTextField getEditorTextField() { + return myDelegate.getEditorComponent(); + } + + @Override + public JComponent getEditorComponent() { + return myPanel; + } + + @Override + public void setItem(Object anObject) { + if (anObject == null) { + anObject = XExpressionImpl.EMPTY_EXPRESSION; + } + XExpression expression = (XExpression)anObject; + myDelegate.getEditorComponent().setNewDocumentAndFileType(getFileType(expression), createDocument(expression)); + } + + @Override + public XExpression getItem() { + Object document = myDelegate.getItem(); + if (document instanceof Document) { // sometimes null on Mac + return getEditorsProvider().createExpression(getProject(), (Document)document, myExpression.getLanguage(), myExpression.getMode()); + } + return null; + } + + @Override + public void selectAll() { + myDelegate.selectAll(); + } + + @Override + public void addActionListener(ActionListener l) { + myDelegate.addActionListener(l); + } + + @Override + public void removeActionListener(ActionListener l) { + myDelegate.removeActionListener(l); + } + } } From cd5b956be5231e434cdb35c00dfb30128793b425 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Sep 2016 17:19:42 +0300 Subject: [PATCH 09/39] project setup --- update-server-mock/.editorconfig | 5 +++++ update-server-mock/.hgignore | 3 +++ update-server-mock/build.gradle | 14 ++++++++++++++ update-server-mock/settings.gradle | 1 + 4 files changed, 23 insertions(+) create mode 100644 update-server-mock/.editorconfig create mode 100644 update-server-mock/.hgignore create mode 100644 update-server-mock/build.gradle create mode 100644 update-server-mock/settings.gradle diff --git a/update-server-mock/.editorconfig b/update-server-mock/.editorconfig new file mode 100644 index 000000000000..e3207ea27130 --- /dev/null +++ b/update-server-mock/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/update-server-mock/.hgignore b/update-server-mock/.hgignore new file mode 100644 index 000000000000..914fca1de2ab --- /dev/null +++ b/update-server-mock/.hgignore @@ -0,0 +1,3 @@ +\.gradle/ +build/ +\.idea/ \ No newline at end of file diff --git a/update-server-mock/build.gradle b/update-server-mock/build.gradle new file mode 100644 index 000000000000..b04b75f3abf3 --- /dev/null +++ b/update-server-mock/build.gradle @@ -0,0 +1,14 @@ +buildscript { + repositories { jcenter() } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:+" + } +} + +apply plugin: 'kotlin' + +repositories { jcenter() } +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.+" + testCompile "junit:junit:4.+" +} \ No newline at end of file diff --git a/update-server-mock/settings.gradle b/update-server-mock/settings.gradle new file mode 100644 index 000000000000..2bb21458e51a --- /dev/null +++ b/update-server-mock/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'update-server-mock' \ No newline at end of file From e04dbd0e5e372b56e836f6173cc9379a50d73c10 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 15 Sep 2016 19:37:02 +0300 Subject: [PATCH 10/39] initial implementation --- update-server-mock/build.gradle | 10 ++ .../org/jetbrains/updater/mock/Generator.kt | 39 ++++++ .../java/org/jetbrains/updater/mock/Server.kt | 130 ++++++++++++++++++ .../java/org/jetbrains/updater/mock/main.kt | 26 ++++ .../src/main/resources/patch/patch.jar | Bin 0 -> 106889 bytes .../jetbrains/updater/mock/GeneratorTest.kt | 31 +++++ 6 files changed, 236 insertions(+) create mode 100644 update-server-mock/src/main/java/org/jetbrains/updater/mock/Generator.kt create mode 100644 update-server-mock/src/main/java/org/jetbrains/updater/mock/Server.kt create mode 100644 update-server-mock/src/main/java/org/jetbrains/updater/mock/main.kt create mode 100644 update-server-mock/src/main/resources/patch/patch.jar create mode 100644 update-server-mock/src/test/java/org/jetbrains/updater/mock/GeneratorTest.kt diff --git a/update-server-mock/build.gradle b/update-server-mock/build.gradle index b04b75f3abf3..63d67a579143 100644 --- a/update-server-mock/build.gradle +++ b/update-server-mock/build.gradle @@ -11,4 +11,14 @@ repositories { jcenter() } dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.+" testCompile "junit:junit:4.+" + testCompile "org.assertj:assertj-core:3.+" +} + +jar { + manifest { + attributes "Main-Class" : "org.jetbrains.updater.mock.MainKt" + } + from { + configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } + } } \ No newline at end of file diff --git a/update-server-mock/src/main/java/org/jetbrains/updater/mock/Generator.kt b/update-server-mock/src/main/java/org/jetbrains/updater/mock/Generator.kt new file mode 100644 index 000000000000..7a5a90e99ba9 --- /dev/null +++ b/update-server-mock/src/main/java/org/jetbrains/updater/mock/Generator.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 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 org.jetbrains.updater.mock + +object Generator { + fun generateXml(productCode: String, buildId: String, eap: Boolean): String { + val status = if (eap) "eap" else "release" + return """ + + + + $productCode + + + +