From 9b8a94494d2eb689d8f04563804d631527678e44 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Thu, 7 Oct 2010 18:40:43 +0400 Subject: [PATCH 01/17] hint setLocation and pack methods refactored --- .../intellij/openapi/ui/popup/JBPopup.java | 2 + .../codeInsight/hint/HintManagerImpl.java | 40 ++------- .../src/com/intellij/ui/HeavyweightHint.java | 10 ++- .../src/com/intellij/ui/Hint.java | 12 ++- .../src/com/intellij/ui/LightweightHint.java | 81 ++++++++++++++----- .../com/intellij/ui/popup/AbstractPopup.java | 12 +++ .../quickFixes/QuickFixManager.java | 2 +- 7 files changed, 104 insertions(+), 55 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopup.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopup.java index db88d602c59a..0ea51772bae2 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopup.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/JBPopup.java @@ -180,4 +180,6 @@ public interface JBPopup extends Disposable, LightweightWindow { void setFinalRunnable(@Nullable Runnable runnable); void moveToFitScreen(); + + Point getLocationOnScreen(); } diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index 0328885ae07f..b5b57879085b 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -210,51 +210,25 @@ public class HintManagerImpl extends HintManager implements Disposable { ((ScrollAwareHint)hint.getComponent()).editorScrolled(); } - if (!hint.isVisible()) { - return; - } + if (!hint.isVisible()) return; Editor editor = e.getEditor(); if (!editor.getComponent().isShowing() || editor.isOneLineMode()) return; Rectangle newRectangle = e.getOldRectangle(); Rectangle oldRectangle = e.getNewRectangle(); - Rectangle bounds = hint.getBounds(); - Point location; - - final Window window = SwingUtilities.getWindowAncestor(hint.getComponent()); - final boolean realPopup = window != null && window != SwingUtilities.getWindowAncestor(editor.getComponent()); - if (realPopup) { - location = window.getLocationOnScreen(); - SwingUtilities.convertPointFromScreen(location, editor.getContentComponent()); - } else { - location = SwingUtilities.convertPoint( - editor.getComponent().getRootPane().getLayeredPane(), - bounds.getLocation(), - editor.getContentComponent() - ); - } + Point location = hint.getLocationOn(editor.getContentComponent()); + Dimension size = hint.getSize(); int xOffset = location.x - oldRectangle.x; int yOffset = location.y - oldRectangle.y; location = new Point(newRectangle.x + xOffset, newRectangle.y + yOffset); - Rectangle newBounds = new Rectangle(location.x, location.y, bounds.width, bounds.height); - - final boolean valid = hideIfOutOfEditor ? oldRectangle.contains(newBounds) : oldRectangle.intersects(newBounds); - if (valid) { - if (!realPopup) { - location = SwingUtilities.convertPoint( - editor.getContentComponent(), - location, - editor.getComponent().getRootPane().getLayeredPane() - ); - hint.updateBounds(location.x, location.y); - } else { - SwingUtilities.convertPointToScreen(location, editor.getContentComponent()); - window.setLocation(location); - } + Rectangle newBounds = new Rectangle(location.x, location.y, size.width, size.height); + final boolean okToUpdateBounds = hideIfOutOfEditor ? oldRectangle.contains(newBounds) : oldRectangle.intersects(newBounds); + if (okToUpdateBounds) { + hint.setLocation(new RelativePoint(editor.getContentComponent(), location)); } else { hint.hide(); diff --git a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java index 963d1db265dc..e6f2553604c3 100644 --- a/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/HeavyweightHint.java @@ -17,6 +17,7 @@ package com.intellij.ui; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.wm.ex.WindowManagerEx; +import com.intellij.ui.awt.RelativePoint; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -94,7 +95,7 @@ public class HeavyweightHint implements Hint { } @Override - public void updateBounds() { + public void pack() { updateBounds(-1, -1, false); } @@ -113,6 +114,13 @@ public class HeavyweightHint implements Hint { } } + @Override + public void setLocation(RelativePoint point) { + if (myWindow != null) { + myWindow.setLocation(point.getScreenPoint().x, point.getScreenPoint().y); + } + } + public void addHintListener(HintListener listener) { myListenerList.add(HintListener.class, listener); } diff --git a/platform/platform-impl/src/com/intellij/ui/Hint.java b/platform/platform-impl/src/com/intellij/ui/Hint.java index d7492e489ccd..4acbb0c639a2 100644 --- a/platform/platform-impl/src/com/intellij/ui/Hint.java +++ b/platform/platform-impl/src/com/intellij/ui/Hint.java @@ -15,6 +15,7 @@ */ package com.intellij.ui; +import com.intellij.ui.awt.RelativePoint; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -41,7 +42,16 @@ public interface Hint { void removeHintListener(HintListener listener); - void updateBounds(); + void pack(); + void setLocation(RelativePoint point); + + /** + * Pack and set location + * @param x + * @param y + * @deprecated use {@link Hint#setLocation(com.intellij.ui.awt.RelativePoint)} ()} + */ void updateBounds(int x, int y); + } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index 4782c989d3a3..095e2ae36159 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -58,6 +58,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { private boolean myResizable; private IdeTooltip myCurrentIdeTooltip; + private HintHint myHintHint; public LightweightHint(@NotNull final JComponent component) { myComponent = component; @@ -107,6 +108,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { final JComponent focusBackComponent, @NotNull final HintHint hintHint) { myParentComponent = parentComponent; + myHintHint = hintHint; myFocusBackComponent = focusBackComponent; @@ -205,10 +207,10 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } public boolean isVisible() { - return myIsRealPopup ? myPopup != null : myComponent.isShowing(); + return myIsRealPopup ? (myPopup != null && myPopup.isVisible()) : myComponent.isShowing(); } - protected final boolean isRealPopup() { + public final boolean isRealPopup() { return myIsRealPopup; } @@ -254,7 +256,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } @Override - public void updateBounds() { + public void pack() { updateBounds(-1, -1, false); } @@ -264,22 +266,9 @@ public class LightweightHint extends UserDataHolderBase implements Hint { } private void updateBounds(int x, int y, boolean updateLocation) { - if (myIsRealPopup) { - if (myPopup == null) return; - if (updateLocation) ((AbstractPopup)myPopup).setLocation(new RelativePoint(myParentComponent, new Point(x, y))); - myPopup.setSize(myComponent.getPreferredSize()); - } - else { - if (updateLocation) { - JLayeredPane layeredPane = myParentComponent.getRootPane().getLayeredPane(); - myComponent.setLocation(SwingUtilities.convertPoint(myParentComponent, x, y, layeredPane)); - - } - Dimension preferredSize = myComponent.getPreferredSize(); - myComponent.setSize(preferredSize.width, preferredSize.height); - - myComponent.validate(); - myComponent.repaint(); + setSize(myComponent.getPreferredSize()); + if (updateLocation) { + setLocation(new RelativePoint(myParentComponent, new Point(x, y))); } } @@ -295,6 +284,60 @@ public class LightweightHint extends UserDataHolderBase implements Hint { myListenerList.remove(HintListener.class, listener); } + public Point getLocationOn(JComponent c) { + Point location; + if (isRealPopup()) { + location = myPopup.getLocationOnScreen(); + SwingUtilities.convertPointFromScreen(location, c); + } else { + location = SwingUtilities.convertPoint( + myComponent.getParent(), + myComponent.getLocation(), + c + ); + } + + return location; + } + + @Override + public void setLocation(RelativePoint point) { + if (isRealPopup()) { + myPopup.setLocation(point.getScreenPoint()); + } else { + if (myHintHint.isAwtTooltip()) { + //todo kirillk + throw new UnsupportedOperationException(); + } else { + Point targetPoint = point.getPoint(myComponent.getParent()); + myComponent.setLocation(targetPoint); + + myComponent.revalidate(); + myComponent.repaint(); + } + } + } + + public void setSize(Dimension size) { + if (myIsRealPopup) { + myPopup.setSize(size); + } else { + //todo kirillk + if (myHintHint.isAwtTooltip()) { + throw new UnsupportedOperationException(); + } else { + myComponent.setSize(size); + + myComponent.revalidate(); + myComponent.repaint(); + } + } + } + + public Dimension getSize() { + return myComponent.getSize(); + } + private final class MyEscListener implements ActionListener { public final void actionPerformed(final ActionEvent e) { hide(); diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index b7d4f67e2565..32372448f71e 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -1136,6 +1136,18 @@ public class AbstractPopup implements JBPopup { return wnd; } + @Override + public Point getLocationOnScreen() { + Dimension headerCorrectionSize = myLocateByContent ? myHeaderPanel.getPreferredSize() : null; + Point screenPoint = myContent.getLocationOnScreen(); + if (headerCorrectionSize != null) { + screenPoint.y -= headerCorrectionSize.height; + } + + return screenPoint; + } + + public void setSize(@NotNull final Dimension size) { if (myPopup == null) { myForcedSize = size; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/QuickFixManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/QuickFixManager.java index 3a74020397b8..3f26f67d58f3 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/QuickFixManager.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/QuickFixManager.java @@ -174,7 +174,7 @@ public abstract class QuickFixManager { Rectangle hintRect = new Rectangle(rc.x - myIcon.getIconWidth() - 4, rc.y, myIcon.getIconWidth() + 4, myIcon.getIconHeight() + 4); LOG.debug("hintRect=" + hintRect); if (getHintClipRect(viewPort).contains(hintRect)) { - myHint.updateBounds(); + myHint.pack(); } else { myHint.hide(); From becb3b9bc7d41cd323616a614acc4f9ff7f963ce Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 8 Oct 2010 15:21:20 +0400 Subject: [PATCH 02/17] traffic lights popup - undead --- .../impl/DaemonTooltipRendererProvider.java | 4 ++-- .../daemon/impl/TrafficTooltipRendererImpl.java | 11 ++++------- .../codeInsight/hint/TooltipController.java | 9 +++++++-- .../src/com/intellij/ide/IdeTooltip.java | 6 ++++-- .../src/com/intellij/ide/IdeTooltipManager.java | 15 +++++++++++++-- .../ex/ErrorStripTooltipRendererProvider.java | 3 ++- .../editor/impl/EditorMarkupModelImpl.java | 9 ++++----- .../src/com/intellij/ui/HintHint.java | 10 ++++++++++ .../src/com/intellij/ui/LightweightHint.java | 8 ++++++-- 9 files changed, 52 insertions(+), 23 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java index 09fb830abf38..694c0006cf2d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java @@ -111,8 +111,8 @@ public class DaemonTooltipRendererProvider implements ErrorStripTooltipRendererP } @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide) { - return new TrafficTooltipRendererImpl(onHide); + public TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor) { + return new TrafficTooltipRendererImpl(onHide, editor); } private static class MyRenderer extends LineTooltipRenderer { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficTooltipRendererImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficTooltipRendererImpl.java index 255fec49dda0..432fca6692e2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficTooltipRendererImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficTooltipRendererImpl.java @@ -24,18 +24,20 @@ import com.intellij.openapi.editor.impl.EditorMarkupModelImpl; import com.intellij.openapi.editor.impl.TrafficTooltipRenderer; import com.intellij.ui.HintHint; import com.intellij.ui.LightweightHint; +import com.intellij.util.ui.update.ComparableObject; import java.awt.*; /** * User: cdr */ -public class TrafficTooltipRendererImpl implements TrafficTooltipRenderer { +public class TrafficTooltipRendererImpl extends ComparableObject.Impl implements TrafficTooltipRenderer { private TrafficProgressPanel myPanel; private final Runnable onHide; private TrafficLightRenderer myTrafficLightRenderer; - public TrafficTooltipRendererImpl(Runnable onHide) { + public TrafficTooltipRendererImpl(Runnable onHide, Editor editor) { + super(editor); this.onHide = onHide; } @@ -69,9 +71,4 @@ public class TrafficTooltipRendererImpl implements TrafficTooltipRenderer { repaintTooltipWindow(); return hint; } - - @Override - public boolean equals(Object obj) { - return obj.getClass() == getClass() && myTrafficLightRenderer == ((TrafficTooltipRendererImpl)obj).myTrafficLightRenderer; - } } diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java index 68ce15a0570b..48d49751d2de 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/TooltipController.java @@ -26,7 +26,6 @@ import com.intellij.ui.LightweightHint; import com.intellij.ui.awt.RelativePoint; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; @@ -57,7 +56,13 @@ public class TooltipController { final boolean alignToRight, @NotNull final TooltipGroup group, final HintHint hintHint) { if (myCurrentTooltip == null || !myCurrentTooltip.isVisible()) { - myCurrentTooltipObject = null; + if (myCurrentTooltip != null) { + if (!IdeTooltipManager.getInstance().isQueuedToShow(myCurrentTooltip.getCurrentIdeTooltip())) { + myCurrentTooltipObject = null; + } + } else { + myCurrentTooltipObject = null; + } } if (Comparing.equal(tooltipObject, myCurrentTooltipObject)) { diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java index d525f5752494..79a9a3a04fe9 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltip.java @@ -17,11 +17,12 @@ package com.intellij.ide; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.registry.Registry; +import com.intellij.util.ui.update.ComparableObject; import javax.swing.*; import java.awt.*; -public class IdeTooltip { +public class IdeTooltip extends ComparableObject.Impl { private Component myComponent; private Point myPoint; @@ -34,7 +35,8 @@ public class IdeTooltip { private boolean myToCenterIfSmall = true; private boolean myHighlighter; - public IdeTooltip(Component component, Point point, JComponent tipComponent) { + public IdeTooltip(Component component, Point point, JComponent tipComponent, Object... identity) { + super(identity); myComponent = component; myPoint = point; myTipComponent = tipComponent; diff --git a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java index c61301e90869..0414db008536 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeTooltipManager.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.ui.popup.BalloonBuilder; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; @@ -31,7 +32,9 @@ import com.intellij.ui.HintHint; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Alarm; import com.intellij.util.IJSwingUtilities; +import com.intellij.util.containers.ComparatorUtil; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.update.ComparableObjectCheck; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,7 +75,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener private IdeTooltip myCurrentTooltip; private Runnable myShowRequest; - + private IdeTooltip myQueuedTooltip; public IdeTooltipManager(JBPopupFactory popupFactory) { @@ -151,7 +154,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener } private void queueShow(final JComponent c, final MouseEvent me, final boolean toCenter) { - final IdeTooltip tooltip = new IdeTooltip(c, me.getPoint(), null) { + final IdeTooltip tooltip = new IdeTooltip(c, me.getPoint(), null, new Object()) { @Override protected boolean beforeShow() { myCurrentEvent = me; @@ -179,6 +182,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener hideCurrent(null); myQueuedComponent = tooltip.getComponent(); + myQueuedTooltip = tooltip; myShowRequest = new Runnable() { @Override @@ -265,6 +269,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener myCurrentTooltip = tooltip; myShowRequest = null; myQueuedComponent = null; + myQueuedTooltip = null; myCurrentTipUi.show(new RelativePoint(tooltip.getComponent(), effectivePoint), tooltip.getPreferredPosition()); myAlarm.addRequest(new Runnable() { @@ -328,6 +333,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener private boolean hideCurrent(@Nullable MouseEvent me) { myShowRequest = null; myQueuedComponent = null; + myQueuedTooltip = null; if (myCurrentTooltip == null) return true; @@ -378,6 +384,7 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener myCurrentTipUi = null; myCurrentComponent = null; myQueuedComponent = null; + myQueuedTooltip = null; myCurrentEvent = null; myCurrentTipIsCentered = false; myX = -1; @@ -538,4 +545,8 @@ public class IdeTooltipManager implements ApplicationComponent, AWTEventListener public String getComponentName() { return "IDE Tooltip Manager"; } + + public boolean isQueuedToShow(IdeTooltip tooltip) { + return Comparing.equal(myQueuedTooltip, tooltip); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java index 97a8b1086c33..195fe6ffcd35 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/ErrorStripTooltipRendererProvider.java @@ -20,6 +20,7 @@ package com.intellij.openapi.editor.ex; import com.intellij.codeInsight.hint.TooltipRenderer; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.impl.TrafficTooltipRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; import org.jetbrains.annotations.NotNull; @@ -33,5 +34,5 @@ public interface ErrorStripTooltipRendererProvider { TooltipRenderer calcTooltipRenderer(@NotNull String text); TooltipRenderer calcTooltipRenderer(@NotNull String text, int width); - TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide); + TrafficTooltipRenderer createTrafficTooltipRenderer(Runnable onHide, Editor editor); } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index 2defd4243717..3c09eaa8d853 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -608,17 +608,15 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark private TrafficTooltipRenderer myTrafficTooltipRenderer; private void showTrafficLightTooltip(MouseEvent e) { - //final String tooltipMessage = myErrorStripeRenderer.getTooltipMessage(); - //if (tooltipMessage == null) return; if (myTrafficTooltipRenderer == null) { myTrafficTooltipRenderer = myTooltipRendererProvider.createTrafficTooltipRenderer(new Runnable() { @Override public void run() { myTrafficTooltipRenderer = null; } - }); + }, myEditor); } - showTooltip(e, myTrafficTooltipRenderer, new HintHint(e).setAwtTooltip(true).setPreferredPosition(Balloon.Position.atLeft)); + showTooltip(e, myTrafficTooltipRenderer, new HintHint(e).setAwtTooltip(true).setMayCenterPosition(true).setContentActive(false).setPreferredPosition(Balloon.Position.atLeft)); } private void repaintTrafficTooltip() { @@ -655,6 +653,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark scrollbar.addMouseListener(handler); myErrorStripeButton.addMouseListener(myHandler); } + } private void showTooltip(MouseEvent e, final TooltipRenderer tooltipObject, HintHint hintHint) { @@ -737,7 +736,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } @Override - public TrafficTooltipRenderer createTrafficTooltipRenderer(final Runnable onHide) { + public TrafficTooltipRenderer createTrafficTooltipRenderer(final Runnable onHide, Editor editor) { return new TrafficTooltipRenderer() { @Override public void repaintTooltipWindow() { diff --git a/platform/platform-impl/src/com/intellij/ui/HintHint.java b/platform/platform-impl/src/com/intellij/ui/HintHint.java index d77a098c98aa..113d2f3a7202 100644 --- a/platform/platform-impl/src/com/intellij/ui/HintHint.java +++ b/platform/platform-impl/src/com/intellij/ui/HintHint.java @@ -36,6 +36,7 @@ public class HintHint { private boolean myContentActive = true; private boolean myQuickHint = false; + private boolean myMayCenterTooltip = false; public HintHint(MouseEvent e) { this(e.getComponent(), e.getPoint()); @@ -55,6 +56,15 @@ public class HintHint { return this; } + public HintHint setMayCenterPosition(boolean mayCenter) { + myMayCenterTooltip = mayCenter; + return this; + } + + public boolean isMayCenterTooltip() { + return myMayCenterTooltip; + } + public HintHint setPreferredPosition(Balloon.Position position) { myPreferredPosition = position; return this; diff --git a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java index 095e2ae36159..f1253b6e205f 100644 --- a/platform/platform-impl/src/com/intellij/ui/LightweightHint.java +++ b/platform/platform-impl/src/com/intellij/ui/LightweightHint.java @@ -127,7 +127,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { if (hintHint.isAwtTooltip()) { - IdeTooltip tooltip = new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent) { + IdeTooltip tooltip = new IdeTooltip(hintHint.getOriginalComponent(), hintHint.getOriginalPoint(), myComponent, hintHint, myComponent) { @Override protected boolean canAutohideOn(TooltipEvent event) { if (event.getInputEvent() instanceof MouseEvent) { @@ -147,7 +147,7 @@ public class LightweightHint extends UserDataHolderBase implements Hint { public boolean canBeDismissedOnTimeout() { return false; } - }.setToCenterIfSmall(false).setPreferredPosition(hintHint.getPreferredPosition()).setHighlighterType(hintHint.isHightlighterType()); + }.setToCenterIfSmall(hintHint.isMayCenterTooltip()).setPreferredPosition(hintHint.getPreferredPosition()).setHighlighterType(hintHint.isHightlighterType()); myComponent.validate(); myCurrentIdeTooltip = IdeTooltipManager.getInstance().show(tooltip, false); @@ -352,4 +352,8 @@ public class LightweightHint extends UserDataHolderBase implements Hint { public boolean canControlAutoHide() { return myCurrentIdeTooltip != null && myCurrentIdeTooltip.getTipComponent().isShowing() ; } + + public IdeTooltip getCurrentIdeTooltip() { + return myCurrentIdeTooltip; + } } From b9fb42d0d2bc76ecc134f77b034166263f285ad9 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 8 Oct 2010 16:18:35 +0400 Subject: [PATCH 03/17] remove big read action --- .../javaCompiler/BackendCompilerWrapper.java | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java index 431e1488d998..444498fcfcbb 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java @@ -520,29 +520,25 @@ public class BackendCompilerWrapper { final List toRefresh = new ArrayList(); final Map> results = new HashMap>(); try { - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - final FileTypeManager typeManager = FileTypeManager.getInstance(); - final String outputDirPath = outputDir.replace(File.separatorChar, '/'); - try { - for (final Module module : chunk.getModules()) { - for (final VirtualFile root : chunk.getSourceRoots(module)) { - final String packagePrefix = myProjectFileIndex.getPackageNameByDirectory(root); - if (LOG.isDebugEnabled()) { - LOG.debug("Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\""); - } - buildOutputItemsList(outputDirPath, module, root, typeManager, root, packagePrefix, toRefresh, results); - } - } - } - catch (CacheCorruptedException e) { - myCompileContext.requestRebuildNextTime(CompilerBundle.message("error.compiler.caches.corrupted")); + final FileTypeManager typeManager = FileTypeManager.getInstance(); + final String outputDirPath = outputDir.replace(File.separatorChar, '/'); + try { + for (final Module module : chunk.getModules()) { + for (final VirtualFile root : chunk.getSourceRoots(module)) { + final String packagePrefix = myProjectFileIndex.getPackageNameByDirectory(root); if (LOG.isDebugEnabled()) { - LOG.debug(e); + LOG.debug("Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\""); } + buildOutputItemsList(outputDirPath, module, root, typeManager, root, packagePrefix, toRefresh, results); } } - }); + } + catch (CacheCorruptedException e) { + myCompileContext.requestRebuildNextTime(CompilerBundle.message("error.compiler.caches.corrupted")); + if (LOG.isDebugEnabled()) { + LOG.debug(e); + } + } } finally { CompilerUtil.refreshIOFiles(toRefresh); @@ -617,11 +613,11 @@ public class BackendCompilerWrapper { paths.add(new CompiledClass(classQName, relativePathToSource, pathToClass)); } - private void updateOutputItemsList(final String outputDir, VirtualFile srcFile, + private void updateOutputItemsList(final String outputDir, final VirtualFile srcFile, VirtualFile sourceRoot, final String packagePrefix, final List filesToRefresh, Map> results, - GlobalSearchScope srcRootScope) throws CacheCorruptedException { + final GlobalSearchScope srcRootScope) throws CacheCorruptedException { final Cache newCache = myCompileContext.getDependencyCache().getNewClassesCache(); final Set paths = myFileNameToSourceMap.get(srcFile.getName()); if (paths == null || paths.isEmpty()) { @@ -638,19 +634,24 @@ public class BackendCompilerWrapper { if (!pathsEquals) { final String qName = myCompileContext.getDependencyCache().resolve(cc.qName); if (qName != null) { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(myProject); - PsiClass psiClass = facade.findClass(qName, srcRootScope); - if (psiClass == null) { - final int dollarIndex = qName.indexOf("$"); - if (dollarIndex >= 0) { - final String topLevelClassName = qName.substring(0, dollarIndex); - psiClass = facade.findClass(topLevelClassName, srcRootScope); + pathsEquals = ApplicationManager.getApplication().runReadAction(new Computable() { + public Boolean compute() { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(myProject); + PsiClass psiClass = facade.findClass(qName, srcRootScope); + if (psiClass == null) { + final int dollarIndex = qName.indexOf("$"); + if (dollarIndex >= 0) { + final String topLevelClassName = qName.substring(0, dollarIndex); + psiClass = facade.findClass(topLevelClassName, srcRootScope); + } + } + if (psiClass != null) { + final VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); + return vFile != null && vFile.equals(srcFile); + } + return false; } - } - if (psiClass != null) { - final VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); - pathsEquals = vFile != null && vFile.equals(srcFile); - } + }); } } From 97a8517cb78102e9e5de842864f3e61987ecc307 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 8 Oct 2010 16:00:29 +0400 Subject: [PATCH 04/17] forbid to change library methods signature --- .../changeSignature/JavaChangeSignatureDetector.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java index e588508992e9..493fc203c876 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.changeSignature; +import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; @@ -23,11 +24,14 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; @@ -65,7 +69,11 @@ public class JavaChangeSignatureDetector implements LanguageChangeSignatureDetec } final MyJavaChangeInfo fromMethod = new MyJavaChangeInfo(newVisibility, method, newReturnType, parameterInfos, null, method.getName()); if (changeInfo == null) { //before replacement - fromMethod.setSuperMethod(method.findDeepestSuperMethod()); + final PsiMethod deepestSuperMethod = method.findDeepestSuperMethod(); + if (deepestSuperMethod != null) { + if (!deepestSuperMethod.getManager().isInProject(deepestSuperMethod)) return null; + } + fromMethod.setSuperMethod(deepestSuperMethod); return fromMethod; } else { final MyJavaChangeInfo info = (MyJavaChangeInfo)changeInfo; From b569ef39e0164d17105d959df00d1b8960528267 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 8 Oct 2010 16:17:16 +0400 Subject: [PATCH 05/17] find usages: search for class: find methods enabled: do not include overload usages --- .../src/com/intellij/find/findUsages/JavaFindUsagesHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java index e01309644010..ea368ffc712b 100644 --- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java +++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java @@ -602,7 +602,7 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{ final PsiClass parentClass = method.getContainingClass(); if (parentClass != null) { - MethodReferencesSearch.search(new MethodReferencesSearch.SearchParameters(method, searchScope, !((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages, options.fastTrack)).forEach(new ReadActionProcessor() { + MethodReferencesSearch.search(new MethodReferencesSearch.SearchParameters(method, searchScope, options instanceof JavaMethodFindUsagesOptions ? !((JavaMethodFindUsagesOptions)options).isIncludeOverloadUsages : true, options.fastTrack)).forEach(new ReadActionProcessor() { public boolean processInReadAction(final PsiReference ref) { return addResult(result, ref, options); } From 683e39720c24b442d2a054b9be59c622763734f1 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 8 Oct 2010 16:29:15 +0400 Subject: [PATCH 06/17] traffic lights popup - restyling --- .../daemon/impl/TrafficProgressPanel.java | 89 +++++++++++++++++-- .../src/messages/DaemonBundle.properties | 20 ++--- 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java index 4e62cca8dfae..2ecea47f0003 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java @@ -27,11 +27,16 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.HintHint; +import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.util.containers.HashMap; import com.intellij.util.containers.hash.LinkedHashMap; +import com.intellij.util.ui.AwtVisitor; import javax.swing.*; +import javax.swing.border.LineBorder; +import java.awt.*; import java.util.ArrayList; import java.util.Map; @@ -39,14 +44,23 @@ import java.util.Map; * User: cdr */ public class TrafficProgressPanel extends JPanel { + + private static final int MAX = 100; + private static final String MAX_TEXT = "100%"; + private static final String MIN_TEXT = "0%"; + private final JLabel statistics = new JLabel(); private final Map> passes = new LinkedHashMap>(); + private Map myProgressToText = new HashMap(); + private final JLabel statusLabel = new JLabel(); private final TrafficLightRenderer myTrafficLightRenderer; private final JPanel passStatuses = new JPanel(); + private HintHint myHintHint; public TrafficProgressPanel(TrafficLightRenderer trafficLightRenderer, Editor editor, HintHint hintHint) { super(new VerticalFlowLayout()); + myHintHint = hintHint; myTrafficLightRenderer = trafficLightRenderer; @@ -70,18 +84,44 @@ public class TrafficProgressPanel extends JPanel { rebuildPassesPanel(fakeStatusLargeEnough); for (Pair pair : passes.values()) { JProgressBar bar = pair.first; - bar.setMaximum(100); + bar.setMaximum(MAX); JLabel label = pair.second; - label.setText("100%"); + label.setText(MAX_TEXT); } add(passStatuses); + add(new Separator()); + add(statistics); updatePanel(fakeStatusLargeEnough); + statistics.setBorder(new LineBorder(Color.red)); + hintHint.initStyle(this, true); } + private class Separator extends NonOpaquePanel { + @Override + protected void paintComponent(Graphics g) { + Insets insets = getInsets(); + if (insets == null) { + insets = new Insets(0, 0, 0, 0); + } + g.setColor(myHintHint.getTextForeground()); + g.drawLine(insets.left, insets.top, getWidth() - insets.left - insets.right, insets.top); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(1, 1); + } + + @Override + public Dimension getMinimumSize() { + return new Dimension(1, 1); + } + } + private void rebuildPassesPanel(TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { passStatuses.removeAll(); passStatuses.setLayout(new GridLayoutManager(Math.max(status.passStati.size(),1), 3)); @@ -89,44 +129,53 @@ public class TrafficProgressPanel extends JPanel { GridConstraints constraints = new GridConstraints(); for (ProgressableTextEditorHighlightingPass pass : status.passStati) { JLabel label = new JLabel(pass.getPresentableName() + ":"); - JProgressBar progressBar = new JProgressBar(0,100); + + JProgressBar progressBar = new JProgressBar(0, MAX); + progressBar.putClientProperty("JComponent.sizeVariant", "mini"); JLabel percLabel = new JLabel(); passes.put(pass, Pair.create(progressBar, percLabel)); + myProgressToText.put(progressBar, percLabel); constraints.setColumn(0); passStatuses.add(label, constraints); constraints.setColumn(1); passStatuses.add(progressBar, constraints); constraints.setColumn(2); passStatuses.add(percLabel, constraints); constraints.setRow(constraints.getRow()+1); } + + myHintHint.initStyle(passStatuses, true); } public void updatePanel(TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { if (status == null) return; if (PowerSaveMode.isEnabled()) { - statusLabel.setText("Code analysis is disabled in power save mode."); + statusLabel.setText("Code analysis is disabled in power save mode"); passStatuses.setVisible(false); statistics.setText(""); return; } if (!status.enabled) { - statusLabel.setText("Code analysis has been suspended."); - passStatuses.setVisible(false); + statusLabel.setText("Code analysis has been suspended"); + passStatuses.setVisible(true); + setPassesEnabled(false, Boolean.FALSE); statistics.setText(""); return; } if (status.noHighlightingRoots != null && status.noHighlightingRoots.length == status.rootsNumber) { statusLabel.setText(DaemonBundle.message("analysis.hasnot.been.run")); - passStatuses.setVisible(false); + passStatuses.setVisible(true); + setPassesEnabled(false, Boolean.FALSE); statistics.setText(""); return; } if (status.errorAnalyzingFinished) { statusLabel.setText(DaemonBundle.message("analysis.completed")); - passStatuses.setVisible(false); + passStatuses.setVisible(true); + setPassesEnabled(false, Boolean.TRUE); } else { statusLabel.setText(DaemonBundle.message("performing.code.analysis")); passStatuses.setVisible(true); + setPassesEnabled(true, null); if (!status.passStati.equals(new ArrayList(passes.keySet()))) { // passes set has changed @@ -137,7 +186,7 @@ public class TrafficProgressPanel extends JPanel { double progress = pass.getProgress(); Pair pair = passes.get(pass); JProgressBar progressBar = pair.first; - int percent = (int)Math.round(progress * 100); + int percent = (int)Math.round(progress * MAX); progressBar.setValue(percent); JLabel percentage = pair.second; percentage.setText(percent + "%"); @@ -164,4 +213,26 @@ public class TrafficProgressPanel extends JPanel { } statistics.setText(text); } + + private void setPassesEnabled(final boolean enabled, final Boolean completed) { + new AwtVisitor(passStatuses) { + @Override + public boolean visit(Component component) { + if (component instanceof JProgressBar) { + JProgressBar progress = (JProgressBar)component; + progress.setEnabled(enabled); + if (completed != null) { + if (completed) { + progress.setValue(MAX); + myProgressToText.get(progress).setText(MAX_TEXT); + } else { + progress.setValue(0); + myProgressToText.get(progress).setText(MIN_TEXT); + } + } + } + return false; + } + }; + } } diff --git a/platform/platform-resources-en/src/messages/DaemonBundle.properties b/platform/platform-resources-en/src/messages/DaemonBundle.properties index a66b57918c1a..25f2b9c07de2 100644 --- a/platform/platform-resources-en/src/messages/DaemonBundle.properties +++ b/platform/platform-resources-en/src/messages/DaemonBundle.properties @@ -9,27 +9,27 @@ method.implements.in=Implements method ''{0}'' in ''{1}'' method.overrides=Overrides method in ''{1}'' method.overrides.in=Overrides method ''{0}'' in ''{1}'' -analysis.hasnot.been.run=No analysis has been performed. +analysis.hasnot.been.run=No analysis has been performed -no.syntax.highlighting.performed=No syntax highlighting performed. -no.inspections.performed=No inspections performed. +no.syntax.highlighting.performed=No syntax highlighting performed +no.inspections.performed=No inspections performed # These two aren't unused! # suppress inspection "UnusedProperty" -no.syntax.highlighting.performed.for=No syntax highlighting performed for {0}. +no.syntax.highlighting.performed.for=No syntax highlighting performed for {0} # suppress inspection "UnusedProperty" -no.inspections.performed.for=No inspections performed {0}. +no.inspections.performed.for=No inspections performed {0} pass.syntax=Syntax analysis pass.inspection=Inspections pass.wolf=Checking red files pass.whole.inspections=Slow Inspections -analysis.completed=Analysis completed. +analysis.completed=Analysis completed -no.errors.or.warnings.found=No errors or warnings found. -no.errors.or.warnings.found.so.far=No errors or warnings found so far. -errors.found.so.far={0} {1} found so far. -errors.found={0} {1} found. +no.errors.or.warnings.found=No errors or warnings found +no.errors.or.warnings.found.so.far=No errors or warnings found so far +errors.found.so.far={0} {1} found so far +errors.found={0} {1} found error.highlighting.settings=Error highlighting settings method.is.implemented.header=Is implemented in
From ed297a1de54d342428b5827b3702c5bed0e45333 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 8 Oct 2010 17:12:26 +0400 Subject: [PATCH 07/17] traffic lights popup - restyling 2 --- .../daemon/impl/TrafficProgressPanel.java | 46 +++++++++++-------- .../src/com/intellij/ui/BalloonImpl.java | 1 + 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java index 2ecea47f0003..13930912b194 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java @@ -21,15 +21,13 @@ import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.HintHint; import com.intellij.ui.components.panels.NonOpaquePanel; -import com.intellij.uiDesigner.core.GridConstraints; -import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.ui.components.panels.VerticalBox; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.ui.AwtVisitor; @@ -59,12 +57,19 @@ public class TrafficProgressPanel extends JPanel { private HintHint myHintHint; public TrafficProgressPanel(TrafficLightRenderer trafficLightRenderer, Editor editor, HintHint hintHint) { - super(new VerticalFlowLayout()); myHintHint = hintHint; myTrafficLightRenderer = trafficLightRenderer; - add(statusLabel); + setLayout(new BorderLayout()); + + VerticalBox center = new VerticalBox(); + add(center, BorderLayout.NORTH); + + center.add(statusLabel); + center.add(new Separator()); + center.add(Box.createVerticalStrut(6)); + TrafficLightRenderer.DaemonCodeAnalyzerStatus fakeStatusLargeEnough = new TrafficLightRenderer.DaemonCodeAnalyzerStatus(); fakeStatusLargeEnough.errorCount = new int[]{1,1,1,1}; Project project = trafficLightRenderer.getProject(); @@ -88,15 +93,11 @@ public class TrafficProgressPanel extends JPanel { JLabel label = pair.second; label.setText(MAX_TEXT); } - add(passStatuses); + center.add(passStatuses); - add(new Separator()); - - add(statistics); + add(statistics, BorderLayout.SOUTH); updatePanel(fakeStatusLargeEnough); - statistics.setBorder(new LineBorder(Color.red)); - hintHint.initStyle(this, true); } @@ -124,24 +125,33 @@ public class TrafficProgressPanel extends JPanel { private void rebuildPassesPanel(TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { passStatuses.removeAll(); - passStatuses.setLayout(new GridLayoutManager(Math.max(status.passStati.size(),1), 3)); + passStatuses.setLayout(new GridBagLayout()); passes.clear(); - GridConstraints constraints = new GridConstraints(); + GridBagConstraints c = new GridBagConstraints(); + c.gridy = 0; + c.fill = GridBagConstraints.HORIZONTAL; for (ProgressableTextEditorHighlightingPass pass : status.passStati) { - JLabel label = new JLabel(pass.getPresentableName() + ":"); + JLabel label = new JLabel(pass.getPresentableName() + ": "); + label.setHorizontalTextPosition(JLabel.RIGHT); JProgressBar progressBar = new JProgressBar(0, MAX); progressBar.putClientProperty("JComponent.sizeVariant", "mini"); JLabel percLabel = new JLabel(); passes.put(pass, Pair.create(progressBar, percLabel)); myProgressToText.put(progressBar, percLabel); - constraints.setColumn(0); passStatuses.add(label, constraints); - constraints.setColumn(1); passStatuses.add(progressBar, constraints); - constraints.setColumn(2); passStatuses.add(percLabel, constraints); - constraints.setRow(constraints.getRow()+1); + c.gridx = 0; + passStatuses.add(label, c); + c.gridx = 1; + passStatuses.add(progressBar, c); + c.gridx = 2; + c.weightx = 1; + passStatuses.add(percLabel, c); + + c.gridy++; } myHintHint.initStyle(passStatuses, true); + statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD)); } public void updatePanel(TrafficLightRenderer.DaemonCodeAnalyzerStatus status) { diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 72a2a120a896..d1784df5402a 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -37,6 +37,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; import java.awt.*; import java.awt.event.*; import java.awt.geom.GeneralPath; From bdb381f9fdb07236182a0988ba81b27abd259c72 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Oct 2010 15:06:51 +0400 Subject: [PATCH 08/17] show correct product name in File Encodings settings (PY-2069) --- .../openapi/vfs/encoding/FileEncodingConfigurable.form | 4 ++-- .../openapi/vfs/encoding/FileEncodingConfigurable.java | 8 +++++++- .../src/messages/IdeBundle.properties | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.form b/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.form index 09ddcc8e4285..fc6ca43d8312 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.form +++ b/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.form @@ -8,7 +8,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.java index 28ff88985d5d..2ec67154b7c5 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.java +++ b/platform/lang-impl/src/com/intellij/openapi/vfs/encoding/FileEncodingConfigurable.java @@ -21,7 +21,11 @@ import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.options.*; +import com.intellij.openapi.application.ApplicationNamesInfo; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.NonDefaultProjectConfigurable; +import com.intellij.openapi.options.OptionalConfigurable; +import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; @@ -51,10 +55,12 @@ public class FileEncodingConfigurable implements SearchableConfigurable, NonDefa private JPanel myPropertiesFilesEncodingCombo; private Charset mySelectedCharsetForPropertiesFiles; private JComboBox myIdeEncodingsCombo; + private JLabel myTitleLabel; private ChooseFileEncodingAction myAction; public FileEncodingConfigurable(Project project) { myProject = project; + myTitleLabel.setText(myTitleLabel.getText().replace("$productName", ApplicationNamesInfo.getInstance().getFullProductName())); } @Nls diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index cbd0908d87e9..84071a7b4a88 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1042,7 +1042,7 @@ finished.with.exit.code.text.message=Process finished with exit code {0} # Encodings file.encodings.configurable=File Encodings encodings.dialog.caption=\ - To change encoding IntelliJ IDEA uses for a file, directory, or an entire project,
\ + To change encoding $productName uses for a file, directory, or an entire project,
\ click an item and then select encoding from the Default Encoding list.
\ Notes:
\ Built-in file encoding (e.g. JSP, HTML or XML) overrides encoding you specify here.
\ From d42dc5d3125ae20fc0c0d7188143658c1f32b3e7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Oct 2010 15:35:50 +0400 Subject: [PATCH 09/17] move non-idea-specific tips to platform (PY-2065) --- .../src/com/intellij/ide/util/TipUIUtil.java | 3 ++- .../src/tips/ColorEditingInCss.html | 4 ++-- .../src/tips/EvaluateExpressionInEditor.html | 0 .../src/tips/IssueNavigation.html | 2 +- .../src/tips/MenuItemsDescriptions.html | 0 .../src/tips/TabInEditorClose.html | 4 ++-- .../src/tips/WordCompletion.html | 0 .../src/tips/images/cssColor.png | Bin .../src/tips/images/issueNavigation.png | Bin .../src/tips/images/issueNavigation1.png | Bin .../src/tips/images/word_completion.gif | Bin resources-en/src/tips/tips.xml | 1 + 12 files changed, 8 insertions(+), 6 deletions(-) rename {resources-en => platform/platform-resources-en}/src/tips/ColorEditingInCss.html (83%) rename {resources-en => platform/platform-resources-en}/src/tips/EvaluateExpressionInEditor.html (100%) rename {resources-en => platform/platform-resources-en}/src/tips/IssueNavigation.html (93%) rename {resources-en => platform/platform-resources-en}/src/tips/MenuItemsDescriptions.html (100%) rename {resources-en => platform/platform-resources-en}/src/tips/TabInEditorClose.html (80%) rename {resources-en => platform/platform-resources-en}/src/tips/WordCompletion.html (100%) rename {resources-en => platform/platform-resources-en}/src/tips/images/cssColor.png (100%) rename {resources-en => platform/platform-resources-en}/src/tips/images/issueNavigation.png (100%) rename {resources-en => platform/platform-resources-en}/src/tips/images/issueNavigation1.png (100%) rename {resources-en => platform/platform-resources-en}/src/tips/images/word_completion.gif (100%) diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java index f63177a3813f..04a88241f66b 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java @@ -61,7 +61,8 @@ public class TipUIUtil { StringBuffer text = new StringBuffer(ResourceUtil.loadText(url)); updateShortcuts(text); - browser.read(new StringReader(text.toString()), null); + String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName()); + browser.read(new StringReader(replaced), null); final Document document = browser.getDocument(); if (document instanceof HTMLDocument) { ((HTMLDocument)document).setBase(url); diff --git a/resources-en/src/tips/ColorEditingInCss.html b/platform/platform-resources-en/src/tips/ColorEditingInCss.html similarity index 83% rename from resources-en/src/tips/ColorEditingInCss.html rename to platform/platform-resources-en/src/tips/ColorEditingInCss.html index 979146f40551..3d7af949994d 100644 --- a/resources-en/src/tips/ColorEditingInCss.html +++ b/platform/platform-resources-en/src/tips/ColorEditingInCss.html @@ -2,8 +2,8 @@ -

IntelliJ - IDEA simplifies working +

&productName; + simplifies working with colors in CSS files. The color properties are marked with the icons of the corresponding color in the left gutter area of the editor. Use these icons to view colors and change color values. When you point with your mouse cursor to the color icon, diff --git a/resources-en/src/tips/EvaluateExpressionInEditor.html b/platform/platform-resources-en/src/tips/EvaluateExpressionInEditor.html similarity index 100% rename from resources-en/src/tips/EvaluateExpressionInEditor.html rename to platform/platform-resources-en/src/tips/EvaluateExpressionInEditor.html diff --git a/resources-en/src/tips/IssueNavigation.html b/platform/platform-resources-en/src/tips/IssueNavigation.html similarity index 93% rename from resources-en/src/tips/IssueNavigation.html rename to platform/platform-resources-en/src/tips/IssueNavigation.html index cc4087a7c8d4..e19c64a46bb5 100644 --- a/resources-en/src/tips/IssueNavigation.html +++ b/platform/platform-resources-en/src/tips/IssueNavigation.html @@ -3,7 +3,7 @@
- Did you know that IntelliJ IDEA lets you jump from your checkin comment to an issue in tracker?
+ Did you know that &productName; lets you jump from your checkin comment to an issue in tracker?
All you have to do is to define issue navigation patterns in the Settings | Version Control dialog:
diff --git a/resources-en/src/tips/MenuItemsDescriptions.html b/platform/platform-resources-en/src/tips/MenuItemsDescriptions.html similarity index 100% rename from resources-en/src/tips/MenuItemsDescriptions.html rename to platform/platform-resources-en/src/tips/MenuItemsDescriptions.html diff --git a/resources-en/src/tips/TabInEditorClose.html b/platform/platform-resources-en/src/tips/TabInEditorClose.html similarity index 80% rename from resources-en/src/tips/TabInEditorClose.html rename to platform/platform-resources-en/src/tips/TabInEditorClose.html index 5fe10df8b5fa..8cc7b69cea5e 100644 --- a/resources-en/src/tips/TabInEditorClose.html +++ b/platform/platform-resources-en/src/tips/TabInEditorClose.html @@ -2,10 +2,10 @@ - + use the Shift+click combination.
Did you know that you can close tabs in the editor and the tool windows of IntelliJ IDEA without actually + Did you know that you can close tabs in the editor and the tool windows of &productName; without actually using the context menu commands? It is enough to point with your mouse cursor to a tab to be closed, and click the middle mouse button, or just - use the shift+click combination.
diff --git a/resources-en/src/tips/WordCompletion.html b/platform/platform-resources-en/src/tips/WordCompletion.html similarity index 100% rename from resources-en/src/tips/WordCompletion.html rename to platform/platform-resources-en/src/tips/WordCompletion.html diff --git a/resources-en/src/tips/images/cssColor.png b/platform/platform-resources-en/src/tips/images/cssColor.png similarity index 100% rename from resources-en/src/tips/images/cssColor.png rename to platform/platform-resources-en/src/tips/images/cssColor.png diff --git a/resources-en/src/tips/images/issueNavigation.png b/platform/platform-resources-en/src/tips/images/issueNavigation.png similarity index 100% rename from resources-en/src/tips/images/issueNavigation.png rename to platform/platform-resources-en/src/tips/images/issueNavigation.png diff --git a/resources-en/src/tips/images/issueNavigation1.png b/platform/platform-resources-en/src/tips/images/issueNavigation1.png similarity index 100% rename from resources-en/src/tips/images/issueNavigation1.png rename to platform/platform-resources-en/src/tips/images/issueNavigation1.png diff --git a/resources-en/src/tips/images/word_completion.gif b/platform/platform-resources-en/src/tips/images/word_completion.gif similarity index 100% rename from resources-en/src/tips/images/word_completion.gif rename to platform/platform-resources-en/src/tips/images/word_completion.gif diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml index 38e9139da496..02d78f926a2e 100644 --- a/resources-en/src/tips/tips.xml +++ b/resources-en/src/tips/tips.xml @@ -103,4 +103,5 @@ + From d5bf59dfe5df60410fc2f041d41084abdc47183f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Oct 2010 15:58:50 +0400 Subject: [PATCH 10/17] move GroovyScript macro to java-impl, as we don't need it anywhere but in IDEA --- java/java-impl/java-impl.iml | 1 + .../intellij/codeInsight/template/macro/GroovyScriptMacro.java | 0 platform/lang-impl/lang-impl.iml | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename {platform/lang-impl => java/java-impl}/src/com/intellij/codeInsight/template/macro/GroovyScriptMacro.java (100%) diff --git a/java/java-impl/java-impl.iml b/java/java-impl/java-impl.iml index 54da7ac1d6cc..72169b16647d 100644 --- a/java/java-impl/java-impl.iml +++ b/java/java-impl/java-impl.iml @@ -26,6 +26,7 @@ + diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/GroovyScriptMacro.java b/java/java-impl/src/com/intellij/codeInsight/template/macro/GroovyScriptMacro.java similarity index 100% rename from platform/lang-impl/src/com/intellij/codeInsight/template/macro/GroovyScriptMacro.java rename to java/java-impl/src/com/intellij/codeInsight/template/macro/GroovyScriptMacro.java diff --git a/platform/lang-impl/lang-impl.iml b/platform/lang-impl/lang-impl.iml index 8826fbdf2382..4d0dc179b794 100644 --- a/platform/lang-impl/lang-impl.iml +++ b/platform/lang-impl/lang-impl.iml @@ -18,7 +18,6 @@ - From d1d960cc9f74afe3ed534005471486002decfc81 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Oct 2010 16:29:27 +0400 Subject: [PATCH 11/17] new platform tips (PY-2064) --- .../src/tips/DragToOpen.html | 10 ++++++++++ .../src/tips/EnterDirectoryInGotoFile.html | 14 ++++++++++++++ .../src/tips/images/dragToOpen.png | Bin 0 -> 40865 bytes .../src/tips/images/enterDirectory.png | Bin 0 -> 12461 bytes resources-en/src/tips/tips.xml | 2 ++ 5 files changed, 26 insertions(+) create mode 100644 platform/platform-resources-en/src/tips/DragToOpen.html create mode 100644 platform/platform-resources-en/src/tips/EnterDirectoryInGotoFile.html create mode 100644 platform/platform-resources-en/src/tips/images/dragToOpen.png create mode 100644 platform/platform-resources-en/src/tips/images/enterDirectory.png diff --git a/platform/platform-resources-en/src/tips/DragToOpen.html b/platform/platform-resources-en/src/tips/DragToOpen.html new file mode 100644 index 000000000000..be9f5a2af9e7 --- /dev/null +++ b/platform/platform-resources-en/src/tips/DragToOpen.html @@ -0,0 +1,10 @@ + +
+ +You can easily open an external file for editing, if you just drag it from the Explorer/Finder to the editor. + + +

+ +
+ diff --git a/platform/platform-resources-en/src/tips/EnterDirectoryInGotoFile.html b/platform/platform-resources-en/src/tips/EnterDirectoryInGotoFile.html new file mode 100644 index 000000000000..45d997c78afa --- /dev/null +++ b/platform/platform-resources-en/src/tips/EnterDirectoryInGotoFile.html @@ -0,0 +1,14 @@ + + + + +You can jump directly to any deeply buried file, if you press &shortcut:GotoFile;, and type just a couple +of characters of the enclosing directories and file names: + +

+ +Use either slash or backslash as the delimiters. + +
+ + \ No newline at end of file diff --git a/platform/platform-resources-en/src/tips/images/dragToOpen.png b/platform/platform-resources-en/src/tips/images/dragToOpen.png new file mode 100644 index 0000000000000000000000000000000000000000..66f3f6d8e21ec01538e1a35ee0a1ffb1732986b0 GIT binary patch literal 40865 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 A5C8xG literal 0 HcmV?d00001 diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml index 02d78f926a2e..f4463faadd44 100644 --- a/resources-en/src/tips/tips.xml +++ b/resources-en/src/tips/tips.xml @@ -104,4 +104,6 @@ + + From e093151afafa488bf5865da9d155e8b48c115055 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 8 Oct 2010 17:38:07 +0400 Subject: [PATCH 12/17] RUBY-5431 Files with two underscores in the name is invisible to the Camel Case file search --- platform/util/src/com/intellij/psi/codeStyle/NameUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index 5b7e60d9a560..3bf3aa65052f 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -159,7 +159,7 @@ public class NameUtil { buffer.append(Character.toLowerCase(c)); } if (!firstIdentifierLetter) { - buffer.append("|[A-Za-z\\s0-9\\$]*[_-]["); + buffer.append("|[A-Za-z\\s0-9\\$]*[_-]+["); buffer.append(c); buffer.append(Character.toLowerCase(c)); buffer.append("]"); @@ -172,7 +172,7 @@ public class NameUtil { buffer.append(Character.toUpperCase(c)); buffer.append(']'); if (lowerCaseWords) { - buffer.append("([a-z\\s0-9\\$]*[-_])?"); + buffer.append("([a-z\\s0-9\\$]*[-_]+)?"); } } else { @@ -195,7 +195,7 @@ public class NameUtil { firstIdentifierLetter = true; } else if (c == ' ') { - buffer.append("([a-z\\s0-9\\$_-]*[\\ _-])+"); + buffer.append("([a-z\\s0-9\\$_-]*[\\ _-]+)+"); firstIdentifierLetter = true; } else { From ea2f89b50c17503378f0a4e421ec5d2b6801d82b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 8 Oct 2010 17:59:51 +0400 Subject: [PATCH 13/17] multithreading disabled by default --- platform/platform-resources-en/src/misc/registry.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 839a7c19dc00..48dfb12ded9d 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -99,4 +99,4 @@ jar.build=false keymap.show.alias.actions=false frameworks.download.libraries.server.url=http://pluginsrepo-test:8080 -caches.indexerThreadsCount=-1 \ No newline at end of file +caches.indexerThreadsCount=1 \ No newline at end of file From c00892910f8a30d2b9e7095dbfc904d5611678ed Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Fri, 8 Oct 2010 18:08:29 +0400 Subject: [PATCH 14/17] do not show unknown run configurations in run configurations popup --- .../actions/ChooseRunConfigurationAction.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java index 0bd51de4f52d..d9d3114b14b9 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationAction.java @@ -18,6 +18,7 @@ package com.intellij.execution.actions; import com.intellij.execution.*; import com.intellij.execution.configurations.ConfigurationType; +import com.intellij.execution.configurations.UnknownConfigurationType; import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.execution.impl.EditConfigurationsDialog; import com.intellij.execution.impl.RunDialog; @@ -452,14 +453,16 @@ public class ChooseRunConfigurationAction extends AnAction { final Map wrappedExisting = new LinkedHashMap(); final ConfigurationType[] factories = manager.getConfigurationFactories(); for (final ConfigurationType factory : factories) { - final RunnerAndConfigurationSettings[] configurations = manager.getConfigurationSettings(factory); - for (final RunnerAndConfigurationSettings configuration : configurations) { - final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration); - if (configuration == selectedConfiguration) { - wrapped.setMnemonic(1); - } + if (!(factory instanceof UnknownConfigurationType)) { + final RunnerAndConfigurationSettings[] configurations = manager.getConfigurationSettings(factory); + for (final RunnerAndConfigurationSettings configuration : configurations) { + final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration); + if (configuration == selectedConfiguration) { + wrapped.setMnemonic(1); + } - wrappedExisting.put(configuration, wrapped); + wrappedExisting.put(configuration, wrapped); + } } } From 132c2eed78e16c82b44532ae1ae066318eec2e43 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 8 Oct 2010 18:08:42 +0400 Subject: [PATCH 15/17] rollback --- .../vfs/newvfs/persistent/FSRecords.java | 54 +++++-------------- .../vfs/newvfs/persistent/PersistentFS.java | 26 ++++----- 2 files changed, 27 insertions(+), 53 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java index 67ef64cd6a65..edd4a4dd1382 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/FSRecords.java @@ -28,7 +28,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.IntArrayList; -import com.intellij.util.io.*; +import com.intellij.util.io.PagedFileStorage; +import com.intellij.util.io.PersistentStringEnumerator; +import com.intellij.util.io.ResizeableMappedFile; import com.intellij.util.io.storage.AbstractStorage; import com.intellij.util.io.storage.HeavyProcessLatch; import com.intellij.util.io.storage.RefCountingStorage; @@ -69,8 +71,6 @@ public class FSRecords implements Disposable, Forceable { private static final int RECORD_SIZE = LENGTH_OFFSET + LENGTH_SIZE; - private final byte[] myRecordBuffer = new byte[RECORD_SIZE]; - private static final byte[] ZEROES = new byte[RECORD_SIZE]; private static final int HEADER_VERSION_OFFSET = 0; @@ -98,20 +98,20 @@ public class FSRecords implements Disposable, Forceable { } private static class DbConnection { - private static int refCount = 0; private static final Object LOCK = new Object(); private static final TObjectIntHashMap myAttributeIds = new TObjectIntHashMap(); - private static PersistentStringEnumerator myNames; + private static PersistentStringEnumerator myNames; private static Storage myAttributes; private static RefCountingStorage myContents; private static ResizeableMappedFile myRecords; private static final TIntArrayList myFreeRecords = new TIntArrayList(); - private static boolean myDirty = false; + private static boolean myDirty = false; private static ScheduledFuture myFlushingFuture; private static boolean myCorrupted = false; + public static DbConnection connect() { synchronized (LOCK) { if (refCount == 0) { @@ -334,6 +334,7 @@ public class FSRecords implements Disposable, Forceable { return myDirty || myNames.isDirty() || myAttributes.isDirty() || myContents.isDirty() || myRecords.isDirty(); } + private static int getVersion() throws IOException { final int recordsVersion = myRecords.getInt(HEADER_VERSION_OFFSET); if (myAttributes.getVersion() != recordsVersion || myContents.getVersion() != recordsVersion) return -1; @@ -341,7 +342,6 @@ public class FSRecords implements Disposable, Forceable { return recordsVersion; } - public static long getTimestamp() { return myRecords.getLong(HEADER_TIMESTAMP_OFFSET); } @@ -434,8 +434,8 @@ public class FSRecords implements Disposable, Forceable { public static void addFreeRecord(final int id) { myFreeRecords.add(id); } - } + public FSRecords() { } @@ -465,7 +465,7 @@ public class FSRecords implements Disposable, Forceable { return DbConnection.getNames(); } - public static int createRecord(boolean clean) { + public static int createRecord() { synchronized (lock) { try { DbConnection.markDirty(); @@ -475,16 +475,12 @@ public class FSRecords implements Disposable, Forceable { final int filelength = (int)getRecords().length(); LOG.assertTrue(filelength % RECORD_SIZE == 0); int newrecord = filelength / RECORD_SIZE; - if (clean) { - DbConnection.cleanRecord(newrecord); - assert filelength + RECORD_SIZE == getRecords().length(); - } + DbConnection.cleanRecord(newrecord); + assert filelength + RECORD_SIZE == getRecords().length(); return newrecord; } else { - if (clean) { - DbConnection.cleanRecord(free); - } + DbConnection.cleanRecord(free); return free; } } @@ -618,7 +614,7 @@ public class FSRecords implements Disposable, Forceable { final DataOutputStream output = writeAttribute(1, CHILDREN_ATT); int id; try { - id = createRecord(true); + id = createRecord(); output.writeInt(names.length + 1); for (int i = 0; i < names.length; i++) { output.writeInt(names[i]); @@ -787,30 +783,6 @@ public class FSRecords implements Disposable, Forceable { } } - public void saveRecord(int id, int parent, String name, long timeStamp, int flags, long length) { - if (id == parent) { - LOG.error("Cyclic parent/child relations"); - return; - } - synchronized (lock) { - try { - DbConnection.markDirty(); - incModCount(id); - Bits.putInt(myRecordBuffer, PARENT_OFFSET, parent); - Bits.putInt(myRecordBuffer, NAME_OFFSET, getNames().enumerate(name)); - Bits.putInt(myRecordBuffer, FLAGS_OFFSET, flags); - Bits.putLong(myRecordBuffer, TIMESTAMP_OFFSET, timeStamp); - Bits.putLong(myRecordBuffer, LENGTH_OFFSET, length); - - getRecords().put(getOffset(id, PARENT_OFFSET), myRecordBuffer, 0, RECORD_SIZE); - - } - catch (Throwable e) { - throw DbConnection.handleError(e); - } - } - } - public static String getName(int id) { synchronized (lock) { try { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java index 120bdc479409..bf689f3aa6da 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java @@ -170,7 +170,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { childrenIds[i] = currentIds[idx]; } else { - int childId = FSRecords.createRecord(false); + int childId = FSRecords.createRecord(); copyRecordFromDelegateFS(childId, id, new FakeVirtualFile(file, name), delegate); childrenIds[i] = childId; } @@ -247,15 +247,21 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } String name = file.getName(); + + if (name.length() > 0 && namesEqual(delegate, name, FSRecords.getName(id))) return; // TODO: Handle root attributes change. + if (name.length() == 0) { // TODO: hack if (areChildrenLoaded(id)) return; } - boolean isDirectory = delegate.isDirectory(file); - int flags = (isDirectory ? IS_DIRECTORY_FLAG : 0) | (delegate.isWritable(file) ? 0 : IS_READ_ONLY); + myRecords.setParent(id, parentId); + myRecords.setName(id, name); + + myRecords.setTimestamp(id, delegate.getTimeStamp(file)); + myRecords.setFlags(id, (delegate.isDirectory(file) ? IS_DIRECTORY_FLAG : 0) | (delegate.isWritable(file) ? 0 : IS_READ_ONLY), true); + + myRecords.setLength(id, -1L); - myRecords.saveRecord(id, parentId, name, delegate.getTimeStamp(file), flags, isDirectory ? -1L : delegate.getLength(file)); - // // TODO!!!: More attributes? } @@ -324,7 +330,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { VirtualFile fake = new FakeVirtualFile(parent, childName); if (delegate.exists(fake)) { - int child = FSRecords.createRecord(false); + int child = FSRecords.createRecord(); copyRecordFromDelegateFS(child, parentId, fake, delegate); myRecords.updateList(parentId, ArrayUtil.append(children, child)); return child; @@ -639,11 +645,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } if (!fs.exists(root)) return null; - String name = root.getName(); - - if (name.length() == 0 || !namesEqual(fs, name, FSRecords.getName(rootId))) { - copyRecordFromDelegateFS(rootId, 0, root, fs); - } + copyRecordFromDelegateFS(rootId, 0, root, fs); } catch (IOException e) { throw new RuntimeException(e); @@ -808,7 +810,7 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { VirtualFile fakeFile = new FakeVirtualFile(parent, name); if (delegate.exists(fakeFile)) { final int parentId = getFileId(parent); - int childId = FSRecords.createRecord(false); + int childId = FSRecords.createRecord(); copyRecordFromDelegateFS(childId, parentId, fakeFile, delegate); appendIdToParentList(parentId, childId); From e4c2ba61543bda2601347fbc1b90e7560f0c2d75 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Fri, 8 Oct 2010 18:14:09 +0400 Subject: [PATCH 16/17] correctly adding/removing listeners in documents --- .../openapi/editor/impl/DocumentImpl.java | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 5c5c5ffbbe09..b1e5f2cd43c9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -77,6 +77,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this); private volatile MarkupModelEx myMarkupModel; + private DocumentListener[] myCachedDocumentListeners; private final List myReadOnlyListeners = new ArrayList(1); private int myCheckGuardedBlocks = 0; @@ -468,12 +469,11 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { return null; // suppress events in shutdown hook } DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced); - //System.out.printf("%nbefore change: offset=%d, old text='%s', new text='%s', document modification stamp=%d%nDocument:'%s'%n", - // event.getOffset(), event.getOldFragment(), event.getNewFragment(), event.getDocument().getModificationStamp(), - // event.getDocument().getText()); - for (int i = myDocumentListeners.size() - 1; i >= 0; i--) { + + DocumentListener[] listeners = getCachedListeners(); + for (int i = listeners.length - 1; i >= 0; i--) { try { - myDocumentListeners.get(i).beforeDocumentChange(event); + listeners[i].beforeDocumentChange(event); } catch (Throwable e) { LOG.error(e); @@ -484,10 +484,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { return event; } - @SuppressWarnings({"ForLoopReplaceableByForEach"}) private void changedUpdate(DocumentEvent event, long newModificationStamp) { - //System.out.printf("after change: new modification stamp=%d%ndocument='%s'%n", event.getDocument().getModificationStamp(), - // event.getDocument().getText()); if (ShutDownTracker.isShutdownHookRunning()) { return; // suppress events in shutdown hook } @@ -497,10 +494,10 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { myLineSet.changedUpdate(event); setModificationStamp(newModificationStamp); - // Don't use for-each in order to avoid unnecessary iterator construction during frequent document updates. - for (int i = 0; i < myDocumentListeners.size(); i++) { + DocumentListener[] listeners = getCachedListeners(); + for (DocumentListener listener : listeners) { try { - myDocumentListeners.get(i).documentChanged(event); + listener.documentChanged(event); } catch (Throwable e) { LOG.error(e); @@ -557,21 +554,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { public void addDocumentListener(@NotNull DocumentListener listener) { + myCachedDocumentListeners = null; LOG.assertTrue(!myDocumentListeners.contains(listener), listener); - if (!(listener instanceof PrioritizedDocumentListener)) { - myDocumentListeners.add(listener); - return; - } - int i = Collections.binarySearch(myDocumentListeners, listener, PrioritizedDocumentListener.COMPARATOR); - if (i < 0) { - i = -i - 1; - } - if (i >= myDocumentListeners.size()) { - myDocumentListeners.add(listener); - } - else { - myDocumentListeners.add(i, listener); - } + myDocumentListeners.add(listener); } public void addDocumentListener(@NotNull final DocumentListener listener, @NotNull Disposable parentDisposable) { @@ -584,6 +569,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { } public void removeDocumentListener(@NotNull DocumentListener listener) { + myCachedDocumentListeners = null; boolean success = myDocumentListeners.remove(listener); LOG.assertTrue(success); } @@ -631,6 +617,15 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { return lineCount; } + private DocumentListener[] getCachedListeners() { + if (myCachedDocumentListeners == null) { + Collections.sort(myDocumentListeners, PrioritizedDocumentListener.COMPARATOR); + myCachedDocumentListeners = myDocumentListeners.toArray(new DocumentListener[myDocumentListeners.size()]); + } + + return myCachedDocumentListeners; + } + public void fireReadOnlyModificationAttempt() { ApplicationManagerEx.getApplicationEx().assertReadAccessToDocumentsAllowed(); EditReadOnlyListener[] listeners = myReadOnlyListeners.toArray( From 17b8359d272fa3368d56cae51c180f9fcc26f503 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Fri, 8 Oct 2010 18:22:20 +0400 Subject: [PATCH 17/17] add drag image for project view dnd --- .../impl/AbstractProjectViewPane.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java index 36bee7ea5b7c..8bd4660eed16 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java @@ -24,7 +24,6 @@ import com.intellij.ide.PsiCopyPasteManager; import com.intellij.ide.SelectInTarget; import com.intellij.ide.dnd.*; import com.intellij.ide.dnd.aware.DnDAwareTree; -import com.intellij.ide.favoritesTreeView.FavoritesTreeViewPanel; import com.intellij.ide.projectView.BaseProjectTreeBuilder; import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.projectView.impl.nodes.AbstractModuleNode; @@ -63,12 +62,10 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.*; -import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.*; +import java.awt.dnd.DnDConstants; +import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -581,7 +578,25 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl @Override public Pair createDraggedImage(DnDAction action, Point dragOrigin) { - return null; + final TreePath[] paths = getSelectionPaths(); + if (paths == null) return null; + + final int count = paths.length; + + final JLabel label = new JLabel(String.format("%s item%s", count, count == 1 ? "" : "s")); + label.setOpaque(true); + label.setForeground(myTree.getForeground()); + label.setBackground(myTree.getBackground()); + label.setFont(myTree.getFont()); + label.setSize(label.getPreferredSize()); + final BufferedImage image = new BufferedImage(label.getWidth(), label.getHeight(), BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2 = (Graphics2D)image.getGraphics(); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); + label.paint(g2); + g2.dispose(); + + return new Pair(image, new Point(-image.getWidth(null), -image.getHeight(null))); } @Override