| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.ide.ui.laf.darcula.ui; |
| |
| import javax.swing.*; |
| import javax.swing.event.MouseInputAdapter; |
| import javax.swing.event.MouseInputListener; |
| import javax.swing.plaf.ComponentUI; |
| import javax.swing.plaf.basic.BasicRootPaneUI; |
| 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 = 16; |
| |
| private static final int BORDER_DRAG_THICKNESS = 5; |
| |
| private Window myWindow; |
| |
| private JComponent myTitlePane; |
| |
| private MouseInputListener myMouseInputListener; |
| |
| private MouseInputListener myTitleMouseInputListener; |
| |
| private LayoutManager myLayoutManager; |
| |
| private LayoutManager myOldLayout; |
| |
| protected JRootPane myRootPane; |
| |
| protected WindowListener myWindowListener; |
| |
| protected Window myCurrentWindow; |
| |
| protected HierarchyListener myHierarchyListener; |
| |
| protected ComponentListener myWindowComponentListener; |
| |
| protected GraphicsConfiguration currentRootPaneGC; |
| |
| protected PropertyChangeListener myPropertyChangeListener; |
| |
| @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") |
| public static ComponentUI createUI(JComponent comp) { |
| return new DarculaRootPaneUI(); |
| } |
| |
| @Override |
| public void installUI(JComponent c) { |
| super.installUI(c); |
| myRootPane = (JRootPane)c; |
| int style = myRootPane.getWindowDecorationStyle(); |
| if (style != JRootPane.NONE) { |
| installClientDecorations(myRootPane); |
| } |
| } |
| |
| @Override |
| public void uninstallUI(JComponent c) { |
| super.uninstallUI(c); |
| uninstallClientDecorations(myRootPane); |
| |
| myLayoutManager = null; |
| myMouseInputListener = null; |
| |
| myRootPane = null; |
| } |
| |
| public void installBorder(JRootPane root) { |
| int style = root.getWindowDecorationStyle(); |
| |
| if (style == JRootPane.NONE) { |
| LookAndFeel.uninstallBorder(root); |
| } |
| else { |
| LookAndFeel.installBorder(root, "RootPane.border"); |
| } |
| } |
| |
| private static void uninstallBorder(JRootPane root) { |
| LookAndFeel.uninstallBorder(root); |
| } |
| |
| |
| private void installWindowListeners(JRootPane root, Component parent) { |
| if (parent instanceof Window) { |
| myWindow = (Window)parent; |
| } |
| else { |
| myWindow = SwingUtilities.getWindowAncestor(parent); |
| } |
| |
| if (myWindow != null) { |
| if (myMouseInputListener == null) { |
| myMouseInputListener = createWindowMouseInputListener(root); |
| } |
| myWindow.addMouseListener(myMouseInputListener); |
| myWindow.addMouseMotionListener(myMouseInputListener); |
| |
| if (myTitlePane != null) { |
| if (myTitleMouseInputListener == null) { |
| myTitleMouseInputListener = new TitleMouseInputHandler(); |
| } |
| myTitlePane |
| .addMouseMotionListener(myTitleMouseInputListener); |
| myTitlePane |
| .addMouseListener(myTitleMouseInputListener); |
| } |
| setMaximized(); |
| } |
| } |
| |
| private void uninstallWindowListeners(JRootPane root) { |
| if (myWindow != null) { |
| myWindow.removeMouseListener(myMouseInputListener); |
| myWindow.removeMouseMotionListener(myMouseInputListener); |
| } |
| if (myTitlePane != null) { |
| myTitlePane.removeMouseListener(myTitleMouseInputListener); |
| myTitlePane.removeMouseMotionListener(myTitleMouseInputListener); |
| } |
| } |
| |
| private void installLayout(JRootPane root) { |
| if (myLayoutManager == null) { |
| myLayoutManager = createLayoutManager(); |
| } |
| myOldLayout = root.getLayout(); |
| root.setLayout(myLayoutManager); |
| } |
| |
| @Override |
| protected void installListeners(final JRootPane root) { |
| super.installListeners(root); |
| |
| myHierarchyListener = new HierarchyListener() { |
| public void hierarchyChanged(HierarchyEvent e) { |
| Component parent = root.getParent(); |
| if (parent == null) { |
| return; |
| } |
| if (parent.getClass().getName().startsWith("org.jdesktop.jdic.tray") |
| || (parent.getClass().getName().compareTo("javax.swing.Popup$HeavyWeightWindow") == 0)) { |
| |
| //noinspection SSBasedInspection |
| SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| root.removeHierarchyListener(myHierarchyListener); |
| myHierarchyListener = null; |
| } |
| }); |
| } |
| |
| Window currWindow; |
| if (parent instanceof Window) { |
| currWindow = (Window)parent; |
| } |
| else { |
| currWindow = SwingUtilities.getWindowAncestor(parent); |
| } |
| if (myWindowListener != null) { |
| myCurrentWindow |
| .removeWindowListener(myWindowListener); |
| myWindowListener = null; |
| } |
| if (myWindowComponentListener != null) { |
| myCurrentWindow |
| .removeComponentListener(myWindowComponentListener); |
| myWindowComponentListener = null; |
| } |
| if (currWindow != null) { |
| myWindowListener = new WindowAdapter() { |
| @Override |
| public void windowClosed(WindowEvent e) { |
| //noinspection SSBasedInspection |
| SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| Frame[] frames = Frame.getFrames(); |
| for (Frame frame : frames) { |
| if (frame.isDisplayable()) { |
| return; |
| } |
| } |
| } |
| }); |
| } |
| }; |
| |
| if (!(parent instanceof JInternalFrame)) { |
| currWindow.addWindowListener(myWindowListener); |
| } |
| |
| myWindowComponentListener = new ComponentAdapter() { |
| @Override |
| public void componentMoved(ComponentEvent e) { |
| processNewPosition(); |
| } |
| |
| @Override |
| public void componentResized(ComponentEvent e) { |
| processNewPosition(); |
| } |
| |
| private void processNewPosition() { |
| //noinspection SSBasedInspection |
| SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| if (myWindow == null) { |
| return; |
| } |
| |
| if (!myWindow.isShowing() |
| || !myWindow.isDisplayable()) { |
| currentRootPaneGC = null; |
| return; |
| } |
| |
| GraphicsEnvironment ge = GraphicsEnvironment |
| .getLocalGraphicsEnvironment(); |
| GraphicsDevice[] gds = ge |
| .getScreenDevices(); |
| if (gds.length == 1) { |
| return; |
| } |
| Point midLoc = new Point(myWindow.getLocationOnScreen().x + myWindow.getWidth() / 2, |
| myWindow.getLocationOnScreen().y + myWindow.getHeight() / 2); |
| |
| for (GraphicsDevice gd : gds) { |
| GraphicsConfiguration gc = gd.getDefaultConfiguration(); |
| Rectangle bounds = gc.getBounds(); |
| if (bounds.contains(midLoc)) { |
| if (gc != currentRootPaneGC) { |
| currentRootPaneGC = gc; |
| setMaximized(); |
| } |
| break; |
| } |
| } |
| } |
| }); |
| } |
| }; |
| |
| if (parent instanceof JFrame) { |
| currWindow.addComponentListener(myWindowComponentListener); |
| } |
| |
| myWindow = currWindow; |
| } |
| myCurrentWindow = currWindow; |
| } |
| }; |
| root.addHierarchyListener(myHierarchyListener); |
| root.addPropertyChangeListener(myPropertyChangeListener); |
| } |
| |
| @Override |
| protected void uninstallListeners(JRootPane root) { |
| if (myWindow != null) { |
| myWindow.removeWindowListener(myWindowListener); |
| myWindowListener = null; |
| myWindow |
| .removeComponentListener(myWindowComponentListener); |
| myWindowComponentListener = null; |
| } |
| root.removeHierarchyListener(myHierarchyListener); |
| myHierarchyListener = null; |
| |
| root.removePropertyChangeListener(myPropertyChangeListener); |
| myPropertyChangeListener = null; |
| |
| super.uninstallListeners(root); |
| } |
| |
| /** |
| * Uninstalls the previously installed <code>LayoutManager</code>. |
| * |
| * @param root Root pane. |
| */ |
| private void uninstallLayout(JRootPane root) { |
| if (myOldLayout != null) { |
| root.setLayout(myOldLayout); |
| myOldLayout = null; |
| } |
| } |
| |
| /** |
| * Installs the necessary state onto the JRootPane to render client |
| * decorations. This is ONLY invoked if the <code>JRootPane</code> has a |
| * decoration style other than <code>JRootPane.NONE</code>. |
| * |
| * @param root Root pane. |
| */ |
| private void installClientDecorations(JRootPane root) { |
| installBorder(root); |
| |
| JComponent titlePane = createTitlePane(root); |
| |
| setTitlePane(root, titlePane); |
| installWindowListeners(root, root.getParent()); |
| installLayout(root); |
| if (myWindow != null) { |
| root.revalidate(); |
| root.repaint(); |
| } |
| } |
| |
| private void uninstallClientDecorations(JRootPane root) { |
| uninstallBorder(root); |
| uninstallWindowListeners(root); |
| setTitlePane(root, null); |
| uninstallLayout(root); |
| int style = root.getWindowDecorationStyle(); |
| if (style == JRootPane.NONE) { |
| root.repaint(); |
| root.revalidate(); |
| } |
| |
| if (myWindow != null) { |
| myWindow.setCursor(Cursor |
| .getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
| } |
| myWindow = null; |
| } |
| |
| protected JComponent createTitlePane(JRootPane root) { |
| return new DarculaTitlePane(root, this); |
| } |
| |
| private MouseInputListener createWindowMouseInputListener(JRootPane root) { |
| return new MouseInputHandler(); |
| } |
| |
| protected LayoutManager createLayoutManager() { |
| return new SubstanceRootLayout(); |
| } |
| |
| private void setTitlePane(JRootPane root, JComponent titlePane) { |
| JLayeredPane layeredPane = root.getLayeredPane(); |
| JComponent oldTitlePane = getTitlePane(); |
| |
| if (oldTitlePane != null) { |
| layeredPane.remove(oldTitlePane); |
| } |
| if (titlePane != null) { |
| layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER); |
| titlePane.setVisible(true); |
| } |
| myTitlePane = titlePane; |
| } |
| |
| public void setMaximized() { |
| Component tla = myRootPane.getTopLevelAncestor(); |
| GraphicsConfiguration gc = (currentRootPaneGC != null) ? currentRootPaneGC |
| : tla.getGraphicsConfiguration(); |
| Rectangle screenBounds = gc.getBounds(); |
| screenBounds.x = 0; |
| screenBounds.y = 0; |
| Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); |
| Rectangle maxBounds = new Rectangle( |
| (screenBounds.x + screenInsets.left), |
| (screenBounds.y + screenInsets.top), screenBounds.width |
| - ((screenInsets.left + screenInsets.right)), |
| screenBounds.height |
| - ((screenInsets.top + screenInsets.bottom))); |
| if (tla instanceof JFrame) { |
| ((JFrame)tla).setMaximizedBounds(maxBounds); |
| } |
| } |
| |
| public JComponent getTitlePane() { |
| return myTitlePane; |
| } |
| |
| protected JRootPane getRootPane() { |
| return myRootPane; |
| } |
| |
| @Override |
| public void propertyChange(PropertyChangeEvent e) { |
| super.propertyChange(e); |
| |
| String propertyName = e.getPropertyName(); |
| if (propertyName == null) { |
| return; |
| } |
| |
| if (propertyName.equals("windowDecorationStyle")) { |
| JRootPane root = (JRootPane)e.getSource(); |
| int style = root.getWindowDecorationStyle(); |
| |
| uninstallClientDecorations(root); |
| if (style != JRootPane.NONE) { |
| installClientDecorations(root); |
| } |
| } |
| if (propertyName.equals("ancestor")) { |
| uninstallWindowListeners(myRootPane); |
| if (((JRootPane)e.getSource()).getWindowDecorationStyle() != JRootPane.NONE) { |
| installWindowListeners(myRootPane, myRootPane.getParent()); |
| } |
| } |
| } |
| |
| protected class SubstanceRootLayout implements LayoutManager2 { |
| public Dimension preferredLayoutSize(Container parent) { |
| Dimension cpd, mbd, tpd; |
| int cpWidth = 0; |
| int cpHeight = 0; |
| int mbWidth = 0; |
| int mbHeight = 0; |
| int tpWidth = 0; |
| int tpHeight = 0; |
| Insets i = parent.getInsets(); |
| JRootPane root = (JRootPane)parent; |
| |
| if (root.getContentPane() != null) { |
| cpd = root.getContentPane().getPreferredSize(); |
| } |
| else { |
| cpd = root.getSize(); |
| } |
| if (cpd != null) { |
| cpWidth = cpd.width; |
| cpHeight = cpd.height; |
| } |
| |
| if (root.getJMenuBar() != null) { |
| mbd = root.getJMenuBar().getPreferredSize(); |
| if (mbd != null) { |
| mbWidth = mbd.width; |
| mbHeight = mbd.height; |
| } |
| } |
| |
| if ((root.getWindowDecorationStyle() != JRootPane.NONE) |
| && (root.getUI() instanceof DarculaRootPaneUI)) { |
| JComponent titlePane = ((DarculaRootPaneUI)root.getUI()).getTitlePane(); |
| if (titlePane != null) { |
| tpd = titlePane.getPreferredSize(); |
| if (tpd != null) { |
| tpWidth = tpd.width; |
| tpHeight = tpd.height; |
| } |
| } |
| } |
| |
| return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) |
| + i.left + i.right, cpHeight + mbHeight + tpHeight + i.top |
| + i.bottom); |
| } |
| |
| public Dimension minimumLayoutSize(Container parent) { |
| Dimension cpd, mbd, tpd; |
| int cpWidth = 0; |
| int cpHeight = 0; |
| int mbWidth = 0; |
| int mbHeight = 0; |
| int tpWidth = 0; |
| int tpHeight = 0; |
| Insets i = parent.getInsets(); |
| JRootPane root = (JRootPane)parent; |
| |
| if (root.getContentPane() != null) { |
| cpd = root.getContentPane().getMinimumSize(); |
| } |
| else { |
| cpd = root.getSize(); |
| } |
| if (cpd != null) { |
| cpWidth = cpd.width; |
| cpHeight = cpd.height; |
| } |
| |
| if (root.getJMenuBar() != null) { |
| mbd = root.getJMenuBar().getMinimumSize(); |
| if (mbd != null) { |
| mbWidth = mbd.width; |
| mbHeight = mbd.height; |
| } |
| } |
| if ((root.getWindowDecorationStyle() != JRootPane.NONE) |
| && (root.getUI() instanceof DarculaRootPaneUI)) { |
| JComponent titlePane = ((DarculaRootPaneUI)root.getUI()) |
| .getTitlePane(); |
| if (titlePane != null) { |
| tpd = titlePane.getMinimumSize(); |
| if (tpd != null) { |
| tpWidth = tpd.width; |
| tpHeight = tpd.height; |
| } |
| } |
| } |
| |
| return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) |
| + i.left + i.right, cpHeight + mbHeight + tpHeight + i.top |
| + i.bottom); |
| } |
| |
| public Dimension maximumLayoutSize(Container target) { |
| Dimension cpd, mbd, tpd; |
| int cpWidth = Integer.MAX_VALUE; |
| int cpHeight = Integer.MAX_VALUE; |
| int mbWidth = Integer.MAX_VALUE; |
| int mbHeight = Integer.MAX_VALUE; |
| int tpWidth = Integer.MAX_VALUE; |
| int tpHeight = Integer.MAX_VALUE; |
| Insets i = target.getInsets(); |
| JRootPane root = (JRootPane)target; |
| |
| if (root.getContentPane() != null) { |
| cpd = root.getContentPane().getMaximumSize(); |
| if (cpd != null) { |
| cpWidth = cpd.width; |
| cpHeight = cpd.height; |
| } |
| } |
| |
| if (root.getJMenuBar() != null) { |
| mbd = root.getJMenuBar().getMaximumSize(); |
| if (mbd != null) { |
| mbWidth = mbd.width; |
| mbHeight = mbd.height; |
| } |
| } |
| |
| if ((root.getWindowDecorationStyle() != JRootPane.NONE) |
| && (root.getUI() instanceof DarculaRootPaneUI)) { |
| JComponent titlePane = ((DarculaRootPaneUI)root.getUI()) |
| .getTitlePane(); |
| if (titlePane != null) { |
| tpd = titlePane.getMaximumSize(); |
| if (tpd != null) { |
| tpWidth = tpd.width; |
| tpHeight = tpd.height; |
| } |
| } |
| } |
| |
| int maxHeight = Math.max(Math.max(cpHeight, mbHeight), tpHeight); |
| if (maxHeight != Integer.MAX_VALUE) { |
| maxHeight = cpHeight + mbHeight + tpHeight + i.top + i.bottom; |
| } |
| |
| int maxWidth = Math.max(Math.max(cpWidth, mbWidth), tpWidth); |
| |
| if (maxWidth != Integer.MAX_VALUE) { |
| maxWidth += i.left + i.right; |
| } |
| |
| return new Dimension(maxWidth, maxHeight); |
| } |
| |
| public void layoutContainer(Container parent) { |
| JRootPane root = (JRootPane)parent; |
| Rectangle b = root.getBounds(); |
| Insets i = root.getInsets(); |
| int nextY = 0; |
| int w = b.width - i.right - i.left; |
| int h = b.height - i.top - i.bottom; |
| |
| if (root.getLayeredPane() != null) { |
| root.getLayeredPane().setBounds(i.left, i.top, w, h); |
| } |
| if (root.getGlassPane() != null) { |
| root.getGlassPane().setBounds(i.left, i.top, w, h); |
| } |
| |
| if ((root.getWindowDecorationStyle() != JRootPane.NONE) |
| && (root.getUI() instanceof DarculaRootPaneUI)) { |
| JComponent titlePane = ((DarculaRootPaneUI)root.getUI()) |
| .getTitlePane(); |
| if (titlePane != null) { |
| Dimension tpd = titlePane.getPreferredSize(); |
| if (tpd != null) { |
| int tpHeight = tpd.height; |
| titlePane.setBounds(0, 0, w, tpHeight); |
| nextY += tpHeight; |
| } |
| } |
| } |
| if (root.getJMenuBar() != null) { |
| Dimension mbd = root.getJMenuBar().getPreferredSize(); |
| root.getJMenuBar().setBounds(0, nextY, w, mbd.height); |
| nextY += mbd.height; |
| } |
| if (root.getContentPane() != null) { |
| |
| root.getContentPane().setBounds(0, nextY, w, h < nextY ? 0 : h - nextY); |
| } |
| } |
| |
| public void addLayoutComponent(String name, Component comp) { |
| } |
| |
| public void removeLayoutComponent(Component comp) { |
| } |
| |
| public void addLayoutComponent(Component comp, Object constraints) { |
| } |
| |
| public float getLayoutAlignmentX(Container target) { |
| return 0.0f; |
| } |
| |
| public float getLayoutAlignmentY(Container target) { |
| return 0.0f; |
| } |
| |
| public void invalidateLayout(Container target) { |
| } |
| } |
| |
| 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 = windowPt.x - dragOffsetX; |
| windowPt.y = 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)) { |
| if (((ev.getClickCount() % 2) == 0) |
| && ((ev.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 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)) { |
| 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); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |