mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
IDEA-270877 Tool windows dnd: add "drag distance" threshold for tool window buttons and headers
IDEA-270760 Highlighting area of a dragged tool window takes the whole editor height GitOrigin-RevId: 67909bb5be94c305b15f3d733593c61ab985e2d2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a2a3048501
commit
ebc002960c
@@ -3,6 +3,7 @@ package com.intellij.openapi.wm;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -47,7 +48,7 @@ public final class ToolWindowAnchor {
|
||||
return this == TOP || this == BOTTOM;
|
||||
}
|
||||
|
||||
public static @NotNull ToolWindowAnchor get(int swingOrientationConstant) {
|
||||
public static @NotNull ToolWindowAnchor get(@MagicConstant(intValues = {SwingConstants.CENTER, SwingConstants.TOP, SwingConstants.LEFT, SwingConstants.BOTTOM, SwingConstants.RIGHT}) int swingOrientationConstant) {
|
||||
switch(swingOrientationConstant) {
|
||||
case SwingConstants.TOP:
|
||||
return TOP;
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.util.Weighted;
|
||||
import com.intellij.openapi.wm.IdeGlassPane;
|
||||
import com.intellij.openapi.wm.IdeGlassPaneUtil;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.update.Activatable;
|
||||
import com.intellij.util.ui.update.UiNotifyConnector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,8 +33,6 @@ public abstract class MouseDragHelper<T extends JComponent> extends MouseAdapter
|
||||
private IdeGlassPane myGlassPane;
|
||||
@NotNull
|
||||
private final Disposable myParentDisposable;
|
||||
private Dimension myDelta;
|
||||
|
||||
private boolean myDetachPostponed;
|
||||
private boolean myDetachingMode;
|
||||
private boolean myCancelled;
|
||||
@@ -124,13 +123,6 @@ public abstract class MouseDragHelper<T extends JComponent> extends MouseAdapter
|
||||
myPressPointScreen = new RelativePoint(e).getScreenPoint();
|
||||
myPressedOnScreenPoint = new Point(myPressPointScreen);
|
||||
processMousePressed(e);
|
||||
|
||||
myDelta = new Dimension();
|
||||
if (myDragComponent.isShowing()) {
|
||||
final Point delta = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), myDragComponent);
|
||||
myDelta.width = delta.x;
|
||||
myDelta.height = delta.y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,9 +260,7 @@ public abstract class MouseDragHelper<T extends JComponent> extends MouseAdapter
|
||||
}
|
||||
|
||||
private boolean isWithinDeadZone(@NotNull MouseEvent e) {
|
||||
final Point screen = new RelativePoint(e).getScreenPoint();
|
||||
return Math.abs(myPressPointScreen.x - screen.x - myDelta.width) < DRAG_START_DEADZONE &&
|
||||
Math.abs(myPressPointScreen.y - screen.y - myDelta.height) < DRAG_START_DEADZONE;
|
||||
return myPressPointScreen.distance(e.getLocationOnScreen()) < JBUI.scale(DRAG_START_DEADZONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.paint.LinePainter2D;
|
||||
import com.intellij.util.ui.JBSwingUtilities;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.StartupUiUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
@@ -32,6 +33,7 @@ class Stripe extends JPanel implements UISettingsListener {
|
||||
private static final Dimension EMPTY_SIZE = new Dimension();
|
||||
static final Key<Rectangle> VIRTUAL_BOUNDS = Key.create("Virtual stripe bounds");
|
||||
|
||||
@MagicConstant(intValues = {SwingConstants.CENTER, SwingConstants.TOP, SwingConstants.LEFT, SwingConstants.BOTTOM, SwingConstants.RIGHT})
|
||||
private final int anchor;
|
||||
private final List<StripeButton> buttons = new ArrayList<>();
|
||||
|
||||
@@ -41,9 +43,9 @@ class Stripe extends JPanel implements UISettingsListener {
|
||||
private JComponent myDragButtonImage;
|
||||
private LayoutData myLastLayoutData;
|
||||
private boolean myFinishingDrop;
|
||||
static final int DROP_DISTANCE_SENSITIVITY = 20;
|
||||
private static final int DROP_DISTANCE_SENSITIVITY = 200;
|
||||
|
||||
Stripe(@MagicConstant(valuesFromClass = SwingConstants.class) int anchor) {
|
||||
Stripe(@MagicConstant(intValues = {SwingConstants.CENTER, SwingConstants.TOP, SwingConstants.LEFT, SwingConstants.BOTTOM, SwingConstants.RIGHT}) int anchor) {
|
||||
super(new GridBagLayout());
|
||||
|
||||
setOpaque(true);
|
||||
@@ -186,9 +188,9 @@ class Stripe extends JPanel implements UISettingsListener {
|
||||
|
||||
data.fitSize = toFitWith != null ? toFitWith : new Dimension();
|
||||
|
||||
Rectangle stripeSensitiveRectangle = new Rectangle(-DROP_DISTANCE_SENSITIVITY, -DROP_DISTANCE_SENSITIVITY,
|
||||
getWidth() + DROP_DISTANCE_SENSITIVITY * 2, getHeight() + DROP_DISTANCE_SENSITIVITY * 2);
|
||||
boolean processDrop = isDroppingButton() && stripeSensitiveRectangle.intersects(myDropRectangle) && !noDrop;
|
||||
Point point = myDropRectangle != null ? myDropRectangle.getLocation() : new Point(-1, -1);
|
||||
SwingUtilities.convertPointToScreen(point, this);
|
||||
boolean processDrop = isDroppingButton() && containsPoint(point) && !noDrop;
|
||||
|
||||
if (toFitWith == null) {
|
||||
for (StripeButton button : buttons) {
|
||||
@@ -447,8 +449,8 @@ class Stripe extends JPanel implements UISettingsListener {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsScreen(@NotNull Rectangle screenRec) {
|
||||
Point point = screenRec.getLocation();
|
||||
boolean containsPoint(@NotNull Point screenPoint) {
|
||||
Point point = screenPoint.getLocation();
|
||||
SwingUtilities.convertPointFromScreen(point, isVisible() ? this : getParent());
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
@@ -461,12 +463,36 @@ class Stripe extends JPanel implements UISettingsListener {
|
||||
height = bounds.height;
|
||||
}
|
||||
}
|
||||
return new Rectangle(point, screenRec.getSize()).intersects(
|
||||
new Rectangle(-DROP_DISTANCE_SENSITIVITY,
|
||||
-DROP_DISTANCE_SENSITIVITY,
|
||||
width + 2 * DROP_DISTANCE_SENSITIVITY,
|
||||
height + 2 * DROP_DISTANCE_SENSITIVITY)
|
||||
);
|
||||
int areaSize = Math.min(Math.min(getParent().getWidth() / 2, getParent().getHeight() / 2), JBUI.scale(DROP_DISTANCE_SENSITIVITY));
|
||||
Point[] points = {new Point(0, 0), new Point(width, 0), new Point(width, height), new Point(0, height)};
|
||||
switch (anchor) {
|
||||
case SwingConstants.TOP: {
|
||||
updateLocation(points, 1, 2, -1, +1, areaSize);
|
||||
updateLocation(points, 0, 3, 1, 1, areaSize);
|
||||
break;
|
||||
}
|
||||
case SwingConstants.LEFT: {
|
||||
updateLocation(points, 0, 1, 1, 1, areaSize);
|
||||
updateLocation(points, 3, 2, 1, -1, areaSize);
|
||||
break;
|
||||
}
|
||||
case SwingConstants.BOTTOM: {
|
||||
updateLocation(points, 3, 0, 1, -1, areaSize);
|
||||
updateLocation(points, 2, 1, -1, -1, areaSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case SwingConstants.RIGHT: {
|
||||
updateLocation(points, 1, 0, -1, 1, areaSize);
|
||||
updateLocation(points, 2, 3, -1, 1, areaSize);
|
||||
}
|
||||
}
|
||||
return new Polygon(new int[]{points[0].x, points[1].x, points[2].x, points[3].x},
|
||||
new int[]{points[0].y, points[1].y, points[2].y, points[3].y}, 4).contains(point);
|
||||
}
|
||||
|
||||
private static void updateLocation(Point[] points, int indexFrom, int indexTo, int xSign, int ySign, int areaSize) {
|
||||
points[indexTo].setLocation(points[indexFrom].x + xSign * areaSize, points[indexFrom].y + ySign * areaSize);
|
||||
}
|
||||
|
||||
public void finishDrop(@NotNull ToolWindowManagerImpl manager) {
|
||||
|
||||
@@ -201,7 +201,7 @@ public class StripeButton extends AnchoredButton implements DataProvider {
|
||||
myDragButtonImage = new JLabel(IconUtil.createImageIcon((Image)image)) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Image for: " + StripeButton.this.toString();
|
||||
return "Image for: " + StripeButton.this;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -235,7 +235,7 @@ public class StripeButton extends AnchoredButton implements DataProvider {
|
||||
|
||||
SwingUtilities.convertPointToScreen(xy, myDragPane);
|
||||
|
||||
Stripe stripe = pane.getStripeFor(new Rectangle(xy, myDragButtonImage.getSize()), (Stripe)getParent());
|
||||
Stripe stripe = pane.getStripeFor(xy, (Stripe)getParent());
|
||||
if (stripe == null) {
|
||||
if (myLastStripe != null) {
|
||||
myLastStripe.resetDrop();
|
||||
|
||||
@@ -89,7 +89,7 @@ internal class ToolWindowDragHelper(parent: @NotNull Disposable,
|
||||
|
||||
override fun processMousePressed(event: MouseEvent) {
|
||||
val relativePoint = RelativePoint(event)
|
||||
val toolWindow = getToolWindow(relativePoint);
|
||||
val toolWindow = getToolWindow(relativePoint)
|
||||
if (toolWindow == null) {
|
||||
return
|
||||
}
|
||||
@@ -150,6 +150,10 @@ internal class ToolWindowDragHelper(parent: @NotNull Disposable,
|
||||
setDragOut(true)
|
||||
return
|
||||
}
|
||||
if (!willDragOutStart && isWithinInitialHeader(event.locationOnScreen)) {
|
||||
cancelDragging()
|
||||
return
|
||||
}
|
||||
val window = getToolWindow()
|
||||
val stripe = myLastStripe
|
||||
if (window != null) {
|
||||
@@ -296,12 +300,7 @@ internal class ToolWindowDragHelper(parent: @NotNull Disposable,
|
||||
dialog.setLocation(screenPoint.x - myInitialOffset.x, screenPoint.y - myInitialOffset.y)
|
||||
setDragOut(dragOut)
|
||||
|
||||
var stripe = myPane.getStripeFor(Rectangle(screenPoint, /*Dimension(dialog.width, dialog.height)*/Dimension(1, 1)),
|
||||
myPane.getStripeFor(myInitialAnchor!!))
|
||||
val fallbackBounds = toolWindow.getBoundsOnScreen(myInitialAnchor!!)
|
||||
if (stripe == null && fallbackBounds.contains(screenPoint)) {
|
||||
stripe = myPane.getStripeFor(myInitialAnchor!!) //fallback
|
||||
}
|
||||
val stripe = getStripe(screenPoint)
|
||||
|
||||
if (myLastStripe != null && myLastStripe != stripe) {
|
||||
myLastStripe!!.resetDrop()
|
||||
@@ -337,7 +336,7 @@ internal class ToolWindowDragHelper(parent: @NotNull Disposable,
|
||||
bounds.height -= half
|
||||
if (dropToSide) {
|
||||
bounds.y += half
|
||||
};
|
||||
}
|
||||
} else {
|
||||
bounds.width -= half
|
||||
if (dropToSide) {
|
||||
@@ -351,6 +350,17 @@ internal class ToolWindowDragHelper(parent: @NotNull Disposable,
|
||||
myLastStripe = stripe
|
||||
}
|
||||
|
||||
private fun getStripe(screenPoint: Point): Stripe? {
|
||||
if (isWithinInitialHeader(screenPoint)) return myPane.getStripeFor(myInitialAnchor!!)
|
||||
return myPane.getStripeFor(screenPoint, myPane.getStripeFor(myInitialAnchor!!))
|
||||
}
|
||||
|
||||
private fun isWithinInitialHeader(screenPoint: Point): Boolean {
|
||||
val toolWindow = getToolWindow()
|
||||
val headerBounds = toolWindow?.decorator?.headerScreenBounds
|
||||
return (headerBounds != null && headerBounds.contains(screenPoint))
|
||||
}
|
||||
|
||||
private fun setDragOut(dragOut: Boolean) {
|
||||
myDialog?.setDragOut(dragOut)
|
||||
myHighlighter.isVisible = !dragOut
|
||||
|
||||
@@ -420,17 +420,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Stripe getStripeFor(@NotNull Rectangle screenRectangle, @NotNull Stripe preferred) {
|
||||
if (!new Rectangle(getLocationOnScreen(), getSize()).intersects(screenRectangle)) {
|
||||
Stripe getStripeFor(@NotNull Point screenPoint, @NotNull Stripe preferred) {
|
||||
if (!new Rectangle(getLocationOnScreen(), getSize()).contains(screenPoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preferred.containsScreen(screenRectangle)) {
|
||||
if (preferred.containsPoint(screenPoint)) {
|
||||
return preferred;
|
||||
}
|
||||
|
||||
for (Stripe stripe : stripes) {
|
||||
if (stripe.containsScreen(screenRectangle)) {
|
||||
if (stripe.containsPoint(screenPoint)) {
|
||||
return stripe;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user