mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-10 22:17:13 -06:00
Window decorations: improved caption hit testing to better support TabbedPane, SplitPane and ToolBar in title bar area (e.g. for fullWindowContent mode)
This commit is contained in:
@@ -257,18 +257,39 @@ public interface FlatClientProperties
|
|||||||
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
String COMPONENT_FOCUS_OWNER = "JComponent.focusOwner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether a component in an embedded menu bar should behave as caption
|
* Specifies whether a component shown in a window title bar area should behave as caption
|
||||||
* (left-click allows moving window, right-click shows window system menu).
|
* (left-click allows moving window, right-click shows window system menu).
|
||||||
* The component does not receive mouse pressed/released/clicked/dragged events,
|
* The caption component does not receive mouse pressed/released/clicked/dragged events,
|
||||||
* but it gets mouse entered/exited/moved events.
|
* but it gets mouse entered/exited/moved events.
|
||||||
* <p>
|
* <p>
|
||||||
|
* Since 3.4, this client property also supports using a function that can check
|
||||||
|
* whether a given location in the component should behave as caption.
|
||||||
|
* Useful for components that do not use mouse input on whole component bounds.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* myComponent.putClientProperty( "JComponent.titleBarCaption",
|
||||||
|
* (Function<Point, Boolean>) pt -> {
|
||||||
|
* // parameter pt contains mouse location (in myComponent coordinates)
|
||||||
|
* // return true if the component is not interested in mouse input at the given location
|
||||||
|
* // return false if the component wants process mouse input at the given location
|
||||||
|
* // return null if the component children should be checked
|
||||||
|
* return ...; // check here
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* <b>Warning</b>:
|
||||||
|
* <ul>
|
||||||
|
* <li>This function is invoked often when mouse is moved over window title bar area
|
||||||
|
* and should therefore return quickly.
|
||||||
|
* <li>This function is invoked on 'AWT-Windows' thread (not 'AWT-EventQueue' thread)
|
||||||
|
* while processing Windows messages.
|
||||||
|
* It <b>must not</b> change any component property or layout because this could cause a dead lock.
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
* <strong>Component</strong> {@link javax.swing.JComponent}<br>
|
||||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
* <strong>Value type</strong> {@link java.lang.Boolean} or {@link java.util.function.Function}<Point, Boolean>
|
||||||
*
|
*
|
||||||
* @since 2.5
|
* @since 2.5
|
||||||
* @deprecated No longer used since FlatLaf 3.4. Retained for API compatibility.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
String COMPONENT_TITLE_BAR_CAPTION = "JComponent.titleBarCaption";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -219,13 +219,13 @@ public class FlatNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
||||||
Predicate<Point> hitTestCallback, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
Predicate<Point> captionHitTestCallback, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||||
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
||||||
{
|
{
|
||||||
if( !isSupported() )
|
if( !isSupported() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nativeProvider.updateTitleBarInfo( window, titleBarHeight, hitTestCallback,
|
nativeProvider.updateTitleBarInfo( window, titleBarHeight, captionHitTestCallback,
|
||||||
appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ public class FlatNativeWindowBorder
|
|||||||
{
|
{
|
||||||
boolean hasCustomDecoration( Window window );
|
boolean hasCustomDecoration( Window window );
|
||||||
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
||||||
void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> hitTestCallback,
|
void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||||
Rectangle closeButtonBounds );
|
Rectangle closeButtonBounds );
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatSplitPaneUI
|
public class FlatSplitPaneUI
|
||||||
extends BasicSplitPaneUI
|
extends BasicSplitPaneUI
|
||||||
implements StyleableUI
|
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||||
{
|
{
|
||||||
@Styleable protected String arrowType;
|
@Styleable protected String arrowType;
|
||||||
/** @since 3.3 */ @Styleable protected Color draggingColor;
|
/** @since 3.3 */ @Styleable protected Color draggingColor;
|
||||||
@@ -227,6 +227,15 @@ public class FlatSplitPaneUI
|
|||||||
((FlatSplitPaneDivider)divider).paintStyle( g, x, y, width, height );
|
((FlatSplitPaneDivider)divider).paintStyle( g, x, y, width, height );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||||
|
|
||||||
|
/** @since 3.4 */
|
||||||
|
@Override
|
||||||
|
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||||
|
// necessary because BasicSplitPaneDivider adds some mouse listeners for dragging divider
|
||||||
|
return null; // check children
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatSplitPaneDivider -----------------------------------------
|
//---- class FlatSplitPaneDivider -----------------------------------------
|
||||||
|
|
||||||
protected class FlatSplitPaneDivider
|
protected class FlatSplitPaneDivider
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatTabbedPaneUI
|
public class FlatTabbedPaneUI
|
||||||
extends BasicTabbedPaneUI
|
extends BasicTabbedPaneUI
|
||||||
implements StyleableUI
|
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||||
{
|
{
|
||||||
// tab type
|
// tab type
|
||||||
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
||||||
@@ -2300,6 +2300,17 @@ debug*/
|
|||||||
return (rects[last].y + rects[last].height) - rects[0].y;
|
return (rects[last].y + rects[last].height) - rects[0].y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||||
|
|
||||||
|
/** @since 3.4 */
|
||||||
|
@Override
|
||||||
|
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||||
|
if( tabForCoordinate( tabPane, x, y ) >= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return null; // check children
|
||||||
|
}
|
||||||
|
|
||||||
//---- class TabCloseButton -----------------------------------------------
|
//---- class TabCloseButton -----------------------------------------------
|
||||||
|
|
||||||
private static class TabCloseButton
|
private static class TabCloseButton
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import java.beans.PropertyChangeEvent;
|
|||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.accessibility.AccessibleContext;
|
import javax.accessibility.AccessibleContext;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.Box;
|
import javax.swing.Box;
|
||||||
@@ -65,6 +66,7 @@ import javax.swing.SwingUtilities;
|
|||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.AbstractBorder;
|
import javax.swing.border.AbstractBorder;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
|
import javax.swing.plaf.ComponentUI;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
import com.formdev.flatlaf.FlatSystemProperties;
|
import com.formdev.flatlaf.FlatSystemProperties;
|
||||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder;
|
import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder;
|
||||||
@@ -314,7 +316,7 @@ public class FlatTitlePane
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear hit-test cache
|
// clear hit-test cache
|
||||||
lastHitTestTime = 0;
|
lastCaptionHitTestTime = 0;
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
@@ -1004,10 +1006,10 @@ public class FlatTitlePane
|
|||||||
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
||||||
|
|
||||||
// clear hit-test cache
|
// clear hit-test cache
|
||||||
lastHitTestTime = 0;
|
lastCaptionHitTestTime = 0;
|
||||||
|
|
||||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
||||||
this::hitTest, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
this::captionHitTest, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||||
|
|
||||||
debugTitleBarHeight = titleBarHeight;
|
debugTitleBarHeight = titleBarHeight;
|
||||||
debugAppIconBounds = appIconBounds;
|
debugAppIconBounds = appIconBounds;
|
||||||
@@ -1024,18 +1026,8 @@ public class FlatTitlePane
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Rectangle getNativeHitTestSpot( JComponent c ) {
|
|
||||||
Dimension size = c.getSize();
|
|
||||||
if( size.width <= 0 || size.height <= 0 )
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Point location = SwingUtilities.convertPoint( c, 0, 0, window );
|
|
||||||
Rectangle r = new Rectangle( location, size );
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns wheter there is a component at the given location, that processes
|
* Returns whether there is a component at the given location, that processes
|
||||||
* mouse events. E.g. buttons, menus, etc.
|
* mouse events. E.g. buttons, menus, etc.
|
||||||
* <p>
|
* <p>
|
||||||
* Note:
|
* Note:
|
||||||
@@ -1046,12 +1038,12 @@ public class FlatTitlePane
|
|||||||
* while processing Windows messages.
|
* while processing Windows messages.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
private boolean hitTest( Point pt ) {
|
private boolean captionHitTest( Point pt ) {
|
||||||
// Windows invokes this method every ~200ms, even if the mouse has not moved
|
// Windows invokes this method every ~200ms, even if the mouse has not moved
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
if( pt.x == lastHitTestX && pt.y == lastHitTestY && time < lastHitTestTime + 300 ) {
|
if( pt.x == lastCaptionHitTestX && pt.y == lastCaptionHitTestY && time < lastCaptionHitTestTime + 300 ) {
|
||||||
lastHitTestTime = time;
|
lastCaptionHitTestTime = time;
|
||||||
return lastHitTestResult;
|
return lastCaptionHitTestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert pt from window coordinates to layeredPane coordinates
|
// convert pt from window coordinates to layeredPane coordinates
|
||||||
@@ -1063,35 +1055,70 @@ public class FlatTitlePane
|
|||||||
y -= c.getY();
|
y -= c.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastHitTestX = pt.x;
|
lastCaptionHitTestX = pt.x;
|
||||||
lastHitTestY = pt.y;
|
lastCaptionHitTestY = pt.y;
|
||||||
lastHitTestTime = time;
|
lastCaptionHitTestTime = time;
|
||||||
lastHitTestResult = isComponentWithMouseListenerAt( layeredPane, x, y );
|
lastCaptionHitTestResult = isTitleBarCaptionAt( layeredPane, x, y );
|
||||||
return lastHitTestResult;
|
return lastCaptionHitTestResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isComponentWithMouseListenerAt( Component c, int x, int y ) {
|
private boolean isTitleBarCaptionAt( Component c, int x, int y ) {
|
||||||
if( !c.isDisplayable() || !c.isVisible() || !c.contains( x, y ) || c == mouseLayer )
|
if( !c.isDisplayable() || !c.isVisible() || !c.contains( x, y ) || c == mouseLayer )
|
||||||
return false;
|
return true; // continue checking with next component
|
||||||
|
|
||||||
if( c.getMouseListeners().length > 0 ||
|
if( c.isEnabled() &&
|
||||||
c.getMouseMotionListeners().length > 0 ||
|
(c.getMouseListeners().length > 0 ||
|
||||||
c.getMouseWheelListeners().length > 0 )
|
c.getMouseMotionListeners().length > 0) )
|
||||||
return true;
|
{
|
||||||
|
if( !(c instanceof JComponent) )
|
||||||
|
return false; // assume that this is not a caption because the component has mouse listeners
|
||||||
|
|
||||||
|
// check client property boolean value
|
||||||
|
Object caption = ((JComponent)c).getClientProperty( COMPONENT_TITLE_BAR_CAPTION );
|
||||||
|
if( caption instanceof Boolean )
|
||||||
|
return (boolean) caption;
|
||||||
|
|
||||||
|
// if component is not fully layouted, do not invoke function
|
||||||
|
// because it is too dangerous that the function tries to layout the component,
|
||||||
|
// which could cause a dead lock
|
||||||
|
if( !c.isValid() )
|
||||||
|
return false; // assume that this is not a caption because the component has mouse listeners
|
||||||
|
|
||||||
|
if( caption instanceof Function ) {
|
||||||
|
// check client property function value
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
Function<Point, Boolean> hitTest = (Function<Point, Boolean>) caption;
|
||||||
|
Boolean result = hitTest.apply( new Point( x, y ) );
|
||||||
|
if( result != null )
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// check component UI
|
||||||
|
ComponentUI ui = JavaCompatibility2.getUI( (JComponent) c );
|
||||||
|
if( !(ui instanceof TitleBarCaptionHitTest) )
|
||||||
|
return false; // assume that this is not a caption because the component has mouse listeners
|
||||||
|
|
||||||
|
Boolean result = ((TitleBarCaptionHitTest)ui).isTitleBarCaptionAt( x, y );
|
||||||
|
if( result != null )
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// else continue checking children
|
||||||
|
}
|
||||||
|
|
||||||
|
// check children
|
||||||
if( c instanceof Container ) {
|
if( c instanceof Container ) {
|
||||||
for( Component child : ((Container)c).getComponents() ) {
|
for( Component child : ((Container)c).getComponents() ) {
|
||||||
if( isComponentWithMouseListenerAt( child, x - child.getX(), y - child.getY() ) )
|
if( !isTitleBarCaptionAt( child, x - child.getX(), y - child.getY() ) )
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int lastHitTestX;
|
private int lastCaptionHitTestX;
|
||||||
private int lastHitTestY;
|
private int lastCaptionHitTestY;
|
||||||
private long lastHitTestTime;
|
private long lastCaptionHitTestTime;
|
||||||
private boolean lastHitTestResult;
|
private boolean lastCaptionHitTestResult;
|
||||||
|
|
||||||
private int debugTitleBarHeight;
|
private int debugTitleBarHeight;
|
||||||
private Rectangle debugAppIconBounds;
|
private Rectangle debugAppIconBounds;
|
||||||
@@ -1490,4 +1517,27 @@ debug*/
|
|||||||
@Override public void componentMoved( ComponentEvent e ) {}
|
@Override public void componentMoved( ComponentEvent e ) {}
|
||||||
@Override public void componentHidden( ComponentEvent e ) {}
|
@Override public void componentHidden( ComponentEvent e ) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface TitleBarCaptionHitTest -----------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For custom components use {@link FlatClientProperties#COMPONENT_TITLE_BAR_CAPTION}
|
||||||
|
* instead of this interface.
|
||||||
|
*
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
public interface TitleBarCaptionHitTest {
|
||||||
|
/**
|
||||||
|
* Invoked for a component that is enabled and has mouse listeners,
|
||||||
|
* to check whether it processes mouse input at the given x/y location.
|
||||||
|
* Useful for components that do not use mouse input on whole component bounds.
|
||||||
|
* E.g. a tabbed pane with a few tabs has some empty space beside the tabs
|
||||||
|
* that can be used to move the window.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the component is not interested in mouse input at the given location
|
||||||
|
* {@code false} if the component wants process mouse input at the given location
|
||||||
|
* {@code null} if the component children should be checked
|
||||||
|
*/
|
||||||
|
Boolean isTitleBarCaptionAt( int x, int y );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
*/
|
*/
|
||||||
public class FlatToolBarUI
|
public class FlatToolBarUI
|
||||||
extends BasicToolBarUI
|
extends BasicToolBarUI
|
||||||
implements StyleableUI
|
implements StyleableUI, FlatTitlePane.TitleBarCaptionHitTest
|
||||||
{
|
{
|
||||||
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
||||||
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
||||||
@@ -453,6 +453,15 @@ public class FlatToolBarUI
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- interface FlatTitlePane.TitleBarCaptionHitTest ----
|
||||||
|
|
||||||
|
/** @since 3.4 */
|
||||||
|
@Override
|
||||||
|
public Boolean isTitleBarCaptionAt( int x, int y ) {
|
||||||
|
// necessary because BasicToolBarUI adds some mouse listeners for dragging when toolbar is floatable
|
||||||
|
return null; // check children
|
||||||
|
}
|
||||||
|
|
||||||
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class FlatWindowsNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> hitTestCallback,
|
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||||
Rectangle closeButtonBounds )
|
Rectangle closeButtonBounds )
|
||||||
{
|
{
|
||||||
@@ -168,7 +168,7 @@ class FlatWindowsNativeWindowBorder
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
wndProc.titleBarHeight = titleBarHeight;
|
wndProc.titleBarHeight = titleBarHeight;
|
||||||
wndProc.hitTestCallback = hitTestCallback;
|
wndProc.captionHitTestCallback = captionHitTestCallback;
|
||||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||||
@@ -289,7 +289,7 @@ class FlatWindowsNativeWindowBorder
|
|||||||
|
|
||||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||||
private int titleBarHeight; // measured from window top edge, which may be out-of-screen if maximized
|
private int titleBarHeight; // measured from window top edge, which may be out-of-screen if maximized
|
||||||
private Predicate<Point> hitTestCallback;
|
private Predicate<Point> captionHitTestCallback;
|
||||||
private Rectangle appIconBounds;
|
private Rectangle appIconBounds;
|
||||||
private Rectangle minimizeButtonBounds;
|
private Rectangle minimizeButtonBounds;
|
||||||
private Rectangle maximizeButtonBounds;
|
private Rectangle maximizeButtonBounds;
|
||||||
@@ -376,7 +376,7 @@ class FlatWindowsNativeWindowBorder
|
|||||||
// that processes mouse events (e.g. buttons, menus, etc)
|
// that processes mouse events (e.g. buttons, menus, etc)
|
||||||
// - Windows ignores mouse events in this area
|
// - Windows ignores mouse events in this area
|
||||||
try {
|
try {
|
||||||
if( hitTestCallback != null && hitTestCallback.test( pt ) )
|
if( captionHitTestCallback != null && !captionHitTestCallback.test( pt ) )
|
||||||
return HTCLIENT;
|
return HTCLIENT;
|
||||||
} catch( Throwable ex ) {
|
} catch( Throwable ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.jideoss.ui;
|
package com.formdev.flatlaf.jideoss.ui;
|
||||||
|
|
||||||
|
import static com.formdev.flatlaf.FlatClientProperties.COMPONENT_TITLE_BAR_CAPTION;
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
|
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_HAS_FULL_BORDER;
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
|
import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_SHOW_TAB_SEPARATORS;
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean;
|
import static com.formdev.flatlaf.FlatClientProperties.clientPropertyBoolean;
|
||||||
@@ -30,6 +31,7 @@ import java.awt.Graphics;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.LayoutManager;
|
import java.awt.LayoutManager;
|
||||||
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
@@ -37,6 +39,7 @@ import java.awt.event.MouseMotionListener;
|
|||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.function.Function;
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
@@ -100,6 +103,25 @@ public class FlatJideTabbedPaneUI
|
|||||||
return new FlatJideTabbedPaneUI();
|
return new FlatJideTabbedPaneUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installUI( JComponent c ) {
|
||||||
|
super.installUI( c );
|
||||||
|
|
||||||
|
c.putClientProperty( COMPONENT_TITLE_BAR_CAPTION,
|
||||||
|
(Function<Point, Boolean>) pt -> {
|
||||||
|
if( tabForCoordinate( _tabPane, pt.x, pt.y ) >= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return null; // check children
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uninstallUI( JComponent c ) {
|
||||||
|
super.uninstallUI( c );
|
||||||
|
c.putClientProperty( COMPONENT_TITLE_BAR_CAPTION, null );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void installDefaults() {
|
protected void installDefaults() {
|
||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> hitTestCallback,
|
public void updateTitleBarInfo( Window window, int titleBarHeight, Predicate<Point> captionHitTestCallback,
|
||||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||||
Rectangle closeButtonBounds )
|
Rectangle closeButtonBounds )
|
||||||
{
|
{
|
||||||
@@ -173,7 +173,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
wndProc.titleBarHeight = titleBarHeight;
|
wndProc.titleBarHeight = titleBarHeight;
|
||||||
wndProc.hitTestCallback = hitTestCallback;
|
wndProc.captionHitTestCallback = captionHitTestCallback;
|
||||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||||
@@ -351,7 +351,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
|
|
||||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||||
private int titleBarHeight;
|
private int titleBarHeight;
|
||||||
private Predicate<Point> hitTestCallback;
|
private Predicate<Point> captionHitTestCallback;
|
||||||
private Rectangle appIconBounds;
|
private Rectangle appIconBounds;
|
||||||
private Rectangle minimizeButtonBounds;
|
private Rectangle minimizeButtonBounds;
|
||||||
private Rectangle maximizeButtonBounds;
|
private Rectangle maximizeButtonBounds;
|
||||||
@@ -684,7 +684,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
// that processes mouse events (e.g. buttons, menus, etc)
|
// that processes mouse events (e.g. buttons, menus, etc)
|
||||||
// - Windows ignores mouse events in this area
|
// - Windows ignores mouse events in this area
|
||||||
try {
|
try {
|
||||||
if( hitTestCallback != null && hitTestCallback.test( pt ) )
|
if( captionHitTestCallback != null && !captionHitTestCallback.test( pt ) )
|
||||||
return new LRESULT( HTCLIENT );
|
return new LRESULT( HTCLIENT );
|
||||||
} catch( Throwable ex ) {
|
} catch( Throwable ex ) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|||||||
Reference in New Issue
Block a user