use shared code to move/resize undecorated frame

This commit is contained in:
Sergey Malenkov
2016-09-07 22:58:52 +03:00
parent 47f3109378
commit f0c23baa29
@@ -18,11 +18,12 @@ package com.intellij.ide.ui.laf.darcula.ui;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.Gray;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.WindowMoveListener;
import com.intellij.ui.WindowResizeListener;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRootPaneUI;
@@ -30,22 +31,11 @@ import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
/**
* @author Konstantin Bulenkov
*/
public class DarculaRootPaneUI extends BasicRootPaneUI {
private Cursor myLastCursor;
private enum CursorState {EXITED, ENTERED, NIL}
private static final int CORNER_DRAG_WIDTH = 5;
private static final int BORDER_DRAG_THICKNESS = 5;
private Window myWindow;
private JComponent myTitlePane;
@@ -141,14 +131,30 @@ public class DarculaRootPaneUI extends BasicRootPaneUI {
if (myWindow != null) {
if (myMouseInputListener == null) {
myMouseInputListener = createWindowMouseInputListener(root);
//noinspection UseDPIAwareInsets
myMouseInputListener = new WindowResizeListener(parent, new Insets(11, 11, 11, 11), null) {
@Override
protected Insets getResizeOffset(Component view) {
return getResizeBorder(view);
}
};
}
myWindow.addMouseListener(myMouseInputListener);
myWindow.addMouseMotionListener(myMouseInputListener);
if (myTitlePane != null) {
if (myTitleMouseInputListener == null) {
myTitleMouseInputListener = new TitleMouseInputHandler();
myTitleMouseInputListener = new WindowMoveListener(myTitlePane) {
@Override
protected boolean isDisabled(Component view) {
if (view instanceof RootPaneContainer) {
RootPaneContainer container = (RootPaneContainer)view;
JRootPane pane = container.getRootPane();
if (pane != null && JRootPane.NONE == pane.getWindowDecorationStyle()) return true;
}
return super.isDisabled(view);
}
};
}
myTitlePane.addMouseMotionListener(myTitleMouseInputListener);
myTitlePane.addMouseListener(myTitleMouseInputListener);
@@ -355,10 +361,6 @@ public class DarculaRootPaneUI extends BasicRootPaneUI {
return new DarculaTitlePane(root, this);
}
private MouseInputListener createWindowMouseInputListener(JRootPane root) {
return new MouseInputHandler();
}
protected LayoutManager createLayoutManager() {
return new DarculaRootLayout();
}
@@ -628,364 +630,6 @@ public class DarculaRootPaneUI extends BasicRootPaneUI {
}
}
private static final int[] cursorMapping = new int[]{
Cursor.NW_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR,
Cursor.N_RESIZE_CURSOR, Cursor.NE_RESIZE_CURSOR,
Cursor.NE_RESIZE_CURSOR, Cursor.NW_RESIZE_CURSOR, 0, 0, 0,
Cursor.NE_RESIZE_CURSOR, Cursor.W_RESIZE_CURSOR, 0, 0, 0,
Cursor.E_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR, 0, 0, 0,
Cursor.SE_RESIZE_CURSOR, Cursor.SW_RESIZE_CURSOR,
Cursor.SW_RESIZE_CURSOR, Cursor.S_RESIZE_CURSOR,
Cursor.SE_RESIZE_CURSOR, Cursor.SE_RESIZE_CURSOR};
private class MouseInputHandler implements MouseInputListener {
private boolean isMovingWindow;
private int dragCursor;
private int dragOffsetX;
private int dragOffsetY;
private int dragWidth;
private int dragHeight;
@SuppressWarnings("unchecked")
private final PrivilegedExceptionAction getLocationAction = new PrivilegedExceptionAction() {
public Object run() throws HeadlessException {
return MouseInfo.getPointerInfo().getLocation();
}
};
public void mousePressed(MouseEvent ev) {
JRootPane rootPane = getRootPane();
if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) {
return;
}
Point dragWindowOffset = ev.getPoint();
Window w = (Window)ev.getSource();
if (w != null) {
w.toFront();
}
Point convertedDragWindowOffset = SwingUtilities.convertPoint(w, dragWindowOffset, getTitlePane());
Frame f = null;
Dialog d = null;
if (w instanceof Frame) {
f = (Frame)w;
}
else if (w instanceof Dialog) {
d = (Dialog)w;
}
int frameState = (f != null) ? f.getExtendedState() : 0;
if ((getTitlePane() != null) && getTitlePane().contains(convertedDragWindowOffset)) {
if ((((f != null) && ((frameState & Frame.MAXIMIZED_BOTH) == 0)) || (d != null))
&& (dragWindowOffset.y >= BORDER_DRAG_THICKNESS)
&& (dragWindowOffset.x >= BORDER_DRAG_THICKNESS)
&& (dragWindowOffset.x < w.getWidth() - BORDER_DRAG_THICKNESS)) {
isMovingWindow = true;
dragOffsetX = dragWindowOffset.x;
dragOffsetY = dragWindowOffset.y;
}
}
else if (((f != null) && f.isResizable() && ((frameState & Frame.MAXIMIZED_BOTH) == 0))
|| ((d != null) && d.isResizable())) {
dragOffsetX = dragWindowOffset.x;
dragOffsetY = dragWindowOffset.y;
dragWidth = w.getWidth();
dragHeight = w.getHeight();
dragCursor = getCursor(calculateCorner(w, dragWindowOffset.x, dragWindowOffset.y));
}
}
public void mouseReleased(MouseEvent ev) {
if ((dragCursor != 0)
&& (myWindow != null)
&& !myWindow.isValid()) {
myWindow.validate();
getRootPane().repaint();
}
isMovingWindow = false;
dragCursor = 0;
}
public void mouseMoved(MouseEvent ev) {
JRootPane root = getRootPane();
if (root.getWindowDecorationStyle() == JRootPane.NONE) {
return;
}
Window w = (Window)ev.getSource();
Frame f = null;
Dialog d = null;
if (w instanceof Frame) {
f = (Frame)w;
}
else if (w instanceof Dialog) {
d = (Dialog)w;
}
int cursor = getCursor(calculateCorner(w, ev.getX(), ev.getY()));
if ((cursor != 0)
&& (((f != null) && (f.isResizable() && ((f.getExtendedState() & Frame.MAXIMIZED_BOTH) == 0)))
|| ((d != null) && d.isResizable()))) {
w.setCursor(Cursor.getPredefinedCursor(cursor));
}
else {
w.setCursor(myLastCursor);
}
}
private void adjust(Rectangle bounds, Dimension min, int deltaX, int deltaY, int deltaWidth, int deltaHeight) {
bounds.x += deltaX;
bounds.y += deltaY;
bounds.width += deltaWidth;
bounds.height += deltaHeight;
if (min != null) {
if (bounds.width < min.width) {
int correction = min.width - bounds.width;
if (deltaX != 0) {
bounds.x -= correction;
}
bounds.width = min.width;
}
if (bounds.height < min.height) {
int correction = min.height - bounds.height;
if (deltaY != 0) {
bounds.y -= correction;
}
bounds.height = min.height;
}
}
}
@SuppressWarnings("unchecked")
public void mouseDragged(MouseEvent ev) {
Window w = (Window)ev.getSource();
Point pt = ev.getPoint();
if (isMovingWindow) {
Point windowPt;
try {
windowPt = (Point)AccessController
.doPrivileged(getLocationAction);
windowPt.x -= dragOffsetX;
windowPt.y -= dragOffsetY;
w.setLocation(windowPt);
}
catch (PrivilegedActionException e) {
}
}
else if (dragCursor != 0) {
Rectangle r = w.getBounds();
Rectangle startBounds = new Rectangle(r);
Dimension min = w.getMinimumSize();
switch (dragCursor) {
case Cursor.E_RESIZE_CURSOR:
adjust(r, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - r.width, 0);
break;
case Cursor.S_RESIZE_CURSOR:
adjust(r, min, 0, 0, 0, pt.y + (dragHeight - dragOffsetY) - r.height);
break;
case Cursor.N_RESIZE_CURSOR:
adjust(r, min, 0, pt.y - dragOffsetY, 0, -(pt.y - dragOffsetY));
break;
case Cursor.W_RESIZE_CURSOR:
adjust(r, min, pt.x - dragOffsetX, 0, -(pt.x - dragOffsetX), 0);
break;
case Cursor.NE_RESIZE_CURSOR:
adjust(r, min, 0, pt.y - dragOffsetY, pt.x + (dragWidth - dragOffsetX) - r.width, -(pt.y - dragOffsetY));
break;
case Cursor.SE_RESIZE_CURSOR:
adjust(r, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - r.width, pt.y + (dragHeight - dragOffsetY) - r.height);
break;
case Cursor.NW_RESIZE_CURSOR:
adjust(r, min, pt.x - dragOffsetX, pt.y - dragOffsetY, -(pt.x - dragOffsetX), -(pt.y - dragOffsetY));
break;
case Cursor.SW_RESIZE_CURSOR:
adjust(r, min, pt.x - dragOffsetX, 0, -(pt.x - dragOffsetX), pt.y + (dragHeight - dragOffsetY) - r.height);
break;
default:
break;
}
if (!r.equals(startBounds)) {
w.setBounds(r);
if (Toolkit.getDefaultToolkit().isDynamicLayoutActive()) {
w.validate();
getRootPane().repaint();
}
}
}
}
private CursorState cursorState = CursorState.NIL;
public void mouseEntered(MouseEvent ev) {
Window w = (Window)ev.getSource();
if (cursorState == CursorState.EXITED || cursorState == CursorState.NIL) {
myLastCursor = w.getCursor();
}
cursorState = CursorState.ENTERED;
mouseMoved(ev);
}
public void mouseExited(MouseEvent ev) {
Window w = (Window)ev.getSource();
w.setCursor(myLastCursor);
cursorState = CursorState.EXITED;
}
public void mouseClicked(MouseEvent ev) {
Window w = (Window)ev.getSource();
Frame f;
if (w instanceof Frame) {
f = (Frame)w;
}
else {
return;
}
JComponent windowTitlePane = getTitlePane();
if (windowTitlePane == null) {
return;
}
Point convertedPoint = SwingUtilities.convertPoint(w, ev.getPoint(), windowTitlePane);
int state = f.getExtendedState();
if (windowTitlePane.contains(convertedPoint)) {
handleMaximize(ev, f, state);
}
}
private int calculateCorner(Window w, int x, int y) {
Insets insets = w.getInsets();
int xPosition = calculatePosition(x - insets.left, w
.getWidth()
- insets.left - insets.right);
int yPosition = calculatePosition(y - insets.top, w
.getHeight()
- insets.top - insets.bottom);
if ((xPosition == -1) || (yPosition == -1)) {
return -1;
}
return yPosition * 5 + xPosition;
}
private int getCursor(int corner) {
if (corner == -1) {
return 0;
}
return cursorMapping[corner];
}
private int calculatePosition(int spot, int width) {
if (spot < BORDER_DRAG_THICKNESS) {
return 0;
}
if (spot < CORNER_DRAG_WIDTH) {
return 1;
}
if (spot >= (width - BORDER_DRAG_THICKNESS)) {
return 4;
}
if (spot >= (width - CORNER_DRAG_WIDTH)) {
return 3;
}
return 2;
}
}
private class TitleMouseInputHandler extends MouseInputAdapter {
private Point dragOffset = new Point(0, 0);
@Override
public void mousePressed(MouseEvent ev) {
JRootPane rootPane = getRootPane();
if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) {
return;
}
Point dragWindowOffset = ev.getPoint();
Component source = (Component)ev.getSource();
Point convertedDragWindowOffset = SwingUtilities.convertPoint(
source, dragWindowOffset, getTitlePane());
dragWindowOffset = SwingUtilities.convertPoint(source, dragWindowOffset, myWindow);
if (getTitlePane() != null && getTitlePane().contains(convertedDragWindowOffset)) {
if (myWindow != null) {
myWindow.toFront();
dragOffset = dragWindowOffset;
}
}
}
@Override
public void mouseDragged(MouseEvent ev) {
Component source = (Component)ev.getSource();
Point eventLocationOnScreen = ev.getLocationOnScreen();
if (eventLocationOnScreen == null) {
eventLocationOnScreen = new Point(ev.getX() + source.getLocationOnScreen().x, ev.getY() + source.getLocationOnScreen().y);
}
if (myWindow instanceof Frame) {
Frame f = (Frame)myWindow;
int frameState = f.getExtendedState();
if (((frameState & Frame.MAXIMIZED_BOTH) == 0)) {
myWindow.setLocation(eventLocationOnScreen.x - dragOffset.x, eventLocationOnScreen.y - dragOffset.y);
}
}
else {
myWindow.setLocation(eventLocationOnScreen.x - dragOffset.x, eventLocationOnScreen.y - dragOffset.y);
}
}
@Override
public void mouseClicked(MouseEvent e) {
Frame f;
if (myWindow instanceof Frame) {
f = (Frame)myWindow;
}
else {
return;
}
Point convertedPoint = SwingUtilities.convertPoint(myWindow, e.getPoint(), getTitlePane());
int state = f.getExtendedState();
if ((getTitlePane() != null) && getTitlePane().contains(convertedPoint)) {
handleMaximize(e, f, state);
}
}
}
private void handleMaximize(MouseEvent e, Frame f, int state) {
if (((e.getClickCount() % 2) == 0) && ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) {
if (f.isResizable()) {
if ((state & Frame.MAXIMIZED_BOTH) != 0) {
setMaximized();
f.setExtendedState(state & ~Frame.MAXIMIZED_BOTH);
}
else {
setMaximized();
f.setExtendedState(state | Frame.MAXIMIZED_BOTH);
}
}
}
}
private static int max(int a, int b, int...others) {
int result = Math.max(a, b);
for (int other : others) {