/* * This file is part of WebLookAndFeel library. * * WebLookAndFeel library is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * WebLookAndFeel library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WebLookAndFeel library. If not, see . */ package com.alee.laf.rootpane; import com.alee.extended.panel.WebButtonGroup; import com.alee.extended.window.ComponentMoveAdapter; import com.alee.global.StyleConstants; import com.alee.laf.WebLookAndFeel; import com.alee.laf.button.WebButton; import com.alee.laf.label.WebLabel; import com.alee.laf.panel.WebPanel; import com.alee.utils.*; import com.alee.utils.ninepatch.NinePatchIcon; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRootPaneUI; import java.awt.*; import java.awt.event.*; import java.awt.geom.RoundRectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; /** * Custom UI for JRootPane component. * This UI also includes custom frame and dialog decorations. * * @author Mikle Garin */ public class WebRootPaneUI extends BasicRootPaneUI implements SwingConstants { /** * todo 1. Resizable using sides when decorated */ /** * Root pane styling icons. */ public static ImageIcon minimizeIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/minimize.png" ) ); public static ImageIcon minimizeActiveIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/minimize_active.png" ) ); public static ImageIcon maximizeIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/maximize.png" ) ); public static ImageIcon maximizeActiveIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/maximize_active.png" ) ); public static ImageIcon restoreIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/restore.png" ) ); public static ImageIcon restoreActiveIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/restore_active.png" ) ); public static ImageIcon closeIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/close.png" ) ); public static ImageIcon closeActiveIcon = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/close_active.png" ) ); /** * Style settings. */ protected Color topBg = WebRootPaneStyle.topBg; protected Color middleBg = WebRootPaneStyle.middleBg; protected Color borderColor = WebRootPaneStyle.borderColor; protected Color innerBorderColor = WebRootPaneStyle.innerBorderColor; protected int shadeWidth = WebRootPaneStyle.shadeWidth; protected int inactiveShadeWidth = WebRootPaneStyle.inactiveShadeWidth; protected int round = WebRootPaneStyle.round; protected Insets margin = WebRootPaneStyle.margin; protected boolean drawWatermark = WebRootPaneStyle.drawWatermark; protected ImageIcon watermark = WebRootPaneStyle.watermark; protected int maxTitleWidth = WebRootPaneStyle.maxTitleWidth; protected String emptyTitleText = " "; /** * Displayed window elements. */ protected boolean showTitleComponent = WebRootPaneStyle.showTitleComponent; protected boolean showMenuBar = WebRootPaneStyle.showMenuBar; protected boolean showWindowButtons = WebRootPaneStyle.showWindowButtons; protected boolean showMinimizeButton = WebRootPaneStyle.showMinimizeButton; protected boolean showMaximizeButton = WebRootPaneStyle.showMaximizeButton; protected boolean showCloseButton = WebRootPaneStyle.showCloseButton; protected boolean groupButtons = WebRootPaneStyle.groupButtons; protected boolean attachButtons = WebRootPaneStyle.attachButtons; protected boolean showResizeCorner = WebRootPaneStyle.showResizeCorner; /** * Runtime variables */ protected boolean styled = false; protected JRootPane root; protected Window window; protected Frame frame; protected Dialog dialog; protected int state; protected LayoutManager layoutManager; protected LayoutManager savedOldLayout; protected WindowFocusListener windowFocusListener; protected PropertyChangeListener titleChangeListener; protected PropertyChangeListener resizableChangeListener; protected WindowStateListener windowStateListener; protected JComponent titleComponent; protected WebButtonGroup windowButtons; protected WebResizeCorner resizeCorner; /** * Returns an instance of the WebRootPaneUI for the specified component. * This tricky method is used by UIManager to create component UIs when needed. * * @param c component that will use UI instance * @return instance of the WebRootPaneUI */ @SuppressWarnings ( "UnusedParameters" ) public static ComponentUI createUI ( final JComponent c ) { return new WebRootPaneUI (); } @Override public void installUI ( final JComponent c ) { super.installUI ( c ); root = ( JRootPane ) c; // Default settings SwingUtils.setOrientation ( root ); root.setBackground ( StyleConstants.backgroundColor ); // Decoration installWindowDecorations (); } @Override public void uninstallUI ( final JComponent c ) { super.uninstallUI ( c ); // Decoration uninstallWindowDecorations (); // Variables layoutManager = null; root = null; } /** * UI parameters */ public boolean isStyled () { return styled; } public Color getTopBg () { return topBg; } public void setTopBg ( final Color topBg ) { this.topBg = topBg; root.repaint (); } public Color getMiddleBg () { return middleBg; } public void setMiddleBg ( final Color middleBg ) { this.middleBg = middleBg; root.repaint (); } public Color getBorderColor () { return borderColor; } public void setBorderColor ( final Color borderColor ) { this.borderColor = borderColor; root.repaint (); } public Color getInnerBorderColor () { return innerBorderColor; } public void setInnerBorderColor ( final Color innerBorderColor ) { this.innerBorderColor = innerBorderColor; root.repaint (); } public int getShadeWidth () { return shadeWidth; } public void setShadeWidth ( final int shadeWidth ) { final int diff = shadeWidth - this.shadeWidth; this.shadeWidth = shadeWidth; if ( styled && window != null ) { final Rectangle b = window.getBounds (); window.setBounds ( b.x - diff, b.y - diff, b.width + diff * 2, b.height + diff * 2 ); installBorder (); root.revalidate (); root.repaint (); } } public int getInactiveShadeWidth () { return inactiveShadeWidth; } public void setInactiveShadeWidth ( final int inactiveShadeWidth ) { this.inactiveShadeWidth = inactiveShadeWidth; if ( styled ) { installBorder (); root.revalidate (); root.repaint (); } } public int getRound () { return round; } public void setRound ( final int round ) { this.round = round; if ( styled ) { updateWindowButtonsStyle (); root.revalidate (); root.repaint (); } } public Insets getMargin () { return margin; } public void setMargin ( final Insets margin ) { this.margin = margin; if ( styled ) { installBorder (); root.revalidate (); root.repaint (); } } public boolean isDrawWatermark () { return drawWatermark; } public void setDrawWatermark ( final boolean drawWatermark ) { this.drawWatermark = drawWatermark; if ( styled ) { root.repaint (); } } public ImageIcon getWatermark () { if ( watermark == null && drawWatermark ) { watermark = new ImageIcon ( WebRootPaneUI.class.getResource ( "icons/watermark.png" ) ); } return watermark; } public void setWatermark ( final ImageIcon watermark ) { this.watermark = watermark; } public int getMaxTitleWidth () { return maxTitleWidth; } public void setMaxTitleWidth ( final int maxTitleWidth ) { this.maxTitleWidth = maxTitleWidth; if ( isStyled () && titleComponent != null ) { titleComponent.revalidate (); titleComponent.repaint (); } } public String getEmptyTitleText () { return emptyTitleText; } public void setEmptyTitleText ( final String emptyTitleText ) { this.emptyTitleText = emptyTitleText; if ( isStyled () && titleComponent != null ) { titleComponent.revalidate (); titleComponent.repaint (); } } public JComponent getTitleComponent () { return titleComponent; } public void setTitleComponent ( final JComponent titleComponent ) { // todo Mark as custom title component this.titleComponent = titleComponent; root.revalidate (); } public WebButtonGroup getWindowButtons () { return windowButtons; } public WebResizeCorner getResizeCorner () { return resizeCorner; } /** * Window elements settings */ public boolean isShowResizeCorner () { return showResizeCorner; } public void setShowResizeCorner ( final boolean showResizeCorner ) { this.showResizeCorner = showResizeCorner; root.revalidate (); } public boolean isShowTitleComponent () { return showTitleComponent; } public void setShowTitleComponent ( final boolean showTitleComponent ) { this.showTitleComponent = showTitleComponent; root.revalidate (); } public boolean isShowWindowButtons () { return showWindowButtons; } public void setShowWindowButtons ( final boolean showWindowButtons ) { this.showWindowButtons = showWindowButtons; root.revalidate (); } public boolean isShowMinimizeButton () { return showMinimizeButton; } public void setShowMinimizeButton ( final boolean showMinimizeButton ) { this.showMinimizeButton = showMinimizeButton; updateButtons (); root.revalidate (); } public boolean isShowMaximizeButton () { return showMaximizeButton; } public void setShowMaximizeButton ( final boolean showMaximizeButton ) { this.showMaximizeButton = showMaximizeButton; updateButtons (); root.revalidate (); } public boolean isShowCloseButton () { return showCloseButton; } public void setShowCloseButton ( final boolean showCloseButton ) { this.showCloseButton = showCloseButton; updateButtons (); root.revalidate (); } public boolean isGroupButtons () { return groupButtons; } public void setGroupButtons ( final boolean groupButtons ) { this.groupButtons = groupButtons; updateButtons (); root.revalidate (); root.repaint (); } public boolean isAttachButtons () { return attachButtons; } public void setAttachButtons ( final boolean attachButtons ) { this.attachButtons = attachButtons; updateButtons (); root.revalidate (); root.repaint (); } public boolean isShowMenuBar () { return showMenuBar; } public void setShowMenuBar ( final boolean showMenuBar ) { this.showMenuBar = showMenuBar; root.revalidate (); } /** * Listening to decoration changes */ @Override public void propertyChange ( final PropertyChangeEvent e ) { super.propertyChange ( e ); final String propertyName = e.getPropertyName (); if ( propertyName == null ) { return; } // Install decorations if ( propertyName.equals ( WebLookAndFeel.WINDOW_DECORATION_STYLE_PROPERTY ) ) { final JRootPane root = ( JRootPane ) e.getSource (); final int style = root.getWindowDecorationStyle (); // Removing old decoration uninstallWindowDecorations (); // Adding new decoration if needed if ( style != JRootPane.NONE ) { installWindowDecorations (); } } } /** * Decoration install and uninstall methods */ protected void installWindowDecorations () { if ( root.getWindowDecorationStyle () != JRootPane.NONE ) { window = root != null ? SwingUtils.getWindowAncestor ( root ) : null; frame = window instanceof Frame ? ( Frame ) window : null; dialog = window instanceof Dialog ? ( Dialog ) window : null; installProperties (); installListeners (); installTransparency (); installBorder (); installLayout (); installDecorationComponents (); styled = true; } } protected void uninstallWindowDecorations () { if ( styled ) { uninstallProperties (); uninstallListeners (); uninstallTransparency (); uninstallBorder (); uninstallLayout (); uninstallDecorationComponents (); window = null; frame = null; dialog = null; styled = false; } } /** * Specific properties */ protected void installProperties () { if ( isFrame () ) { // Maximum frame size frame.setMaximizedBounds ( GraphicsEnvironment.getLocalGraphicsEnvironment ().getMaximumWindowBounds () ); } } protected void uninstallProperties () { if ( isFrame () ) { // Maximum frame size frame.setMaximizedBounds ( null ); } } /** * Listeners */ protected void installListeners () { windowFocusListener = new WindowFocusListener () { @Override public void windowGainedFocus ( final WindowEvent e ) { root.repaint (); } @Override public void windowLostFocus ( final WindowEvent e ) { root.repaint (); } }; window.addWindowFocusListener ( windowFocusListener ); // Listen to window icon and title changes titleChangeListener = new PropertyChangeListener () { @Override public void propertyChange ( final PropertyChangeEvent evt ) { titleComponent.revalidate (); titleComponent.repaint (); } }; window.addPropertyChangeListener ( WebLookAndFeel.WINDOW_ICON_PROPERTY, titleChangeListener ); window.addPropertyChangeListener ( WebLookAndFeel.WINDOW_TITLE_PROPERTY, titleChangeListener ); // Listen to window resizability changes resizableChangeListener = new PropertyChangeListener () { @Override public void propertyChange ( final PropertyChangeEvent evt ) { updateButtons (); } }; window.addPropertyChangeListener ( WebLookAndFeel.WINDOW_RESIZABLE_PROPERTY, resizableChangeListener ); if ( isFrame () ) { state = frame.getState (); windowStateListener = new WindowStateListener () { @Override public void windowStateChanged ( final WindowEvent e ) { state = e.getNewState (); installBorder (); } }; window.addWindowStateListener ( windowStateListener ); } } protected void uninstallListeners () { window.removeWindowFocusListener ( windowFocusListener ); window.removePropertyChangeListener ( WebLookAndFeel.WINDOW_ICON_PROPERTY, titleChangeListener ); window.removePropertyChangeListener ( WebLookAndFeel.WINDOW_TITLE_PROPERTY, titleChangeListener ); window.removePropertyChangeListener ( WebLookAndFeel.WINDOW_RESIZABLE_PROPERTY, resizableChangeListener ); if ( isFrame () ) { window.removeWindowStateListener ( windowStateListener ); } } /** * Window transparency */ protected void installTransparency () { if ( ProprietaryUtils.isWindowTransparencyAllowed () ) { root.setOpaque ( false ); ProprietaryUtils.setWindowOpaque ( window, false ); } } protected void uninstallTransparency () { if ( ProprietaryUtils.isWindowTransparencyAllowed () ) { root.setOpaque ( true ); ProprietaryUtils.setWindowOpaque ( window, true ); } } /** * Decoration border install and uninstall methods */ protected void installBorder () { if ( !isFrameMaximized () ) { root.setBorder ( BorderFactory .createEmptyBorder ( shadeWidth + 1 + margin.top, shadeWidth + 1 + margin.left, shadeWidth + 1 + margin.bottom, shadeWidth + 1 + margin.right ) ); } else { root.setBorder ( BorderFactory.createEmptyBorder ( 1 + margin.top, 1 + margin.left, 1 + margin.bottom, 1 + margin.right ) ); } } protected void uninstallBorder () { root.setBorder ( null ); } /** * Appropriate LayoutManager for the window decorations install and uninstall methods */ protected void installLayout () { if ( layoutManager == null ) { layoutManager = new WebRootPaneLayout (); } savedOldLayout = root.getLayout (); root.setLayout ( layoutManager ); } protected void uninstallLayout () { if ( savedOldLayout != null ) { root.setLayout ( savedOldLayout ); savedOldLayout = null; } } /** * Resize corner */ protected void installDecorationComponents () { // Title titleComponent = createDefaultTitleComponent (); root.add ( titleComponent ); // Buttons updateButtons (); // Resize corner resizeCorner = new WebResizeCorner (); root.add ( resizeCorner ); } protected JComponent createDefaultTitleComponent () { final WebLabel titleIcon = new WebLabel () { @Override public Icon getIcon () { return getWindowIcon (); } }; final TitleLabel titleLabel = new TitleLabel (); titleLabel.setDrawShade ( true ); titleLabel.setHorizontalAlignment ( WebLabel.CENTER ); titleLabel.addComponentListener ( new ComponentAdapter () { @Override public void componentResized ( final ComponentEvent e ) { titleLabel.setHorizontalAlignment ( titleLabel.getRequiredSize ().width > titleLabel.getWidth () ? LEADING : CENTER ); } } ); SwingUtils.setFontSize ( titleLabel, 13 ); // Window move and max/restore listener final ComponentMoveAdapter cma = new ComponentMoveAdapter () { @Override public void mouseClicked ( final MouseEvent e ) { if ( isFrame () && isShowMaximizeButton () && SwingUtils.isLeftMouseButton ( e ) && e.getClickCount () == 2 ) { if ( isFrameMaximized () ) { restore (); } else { maximize (); } } } @Override public void mouseDragged ( final MouseEvent e ) { if ( dragging && isFrameMaximized () ) { initialPoint = new Point ( initialPoint.x + shadeWidth, initialPoint.y + shadeWidth ); restore (); } super.mouseDragged ( e ); } }; titleLabel.addMouseListener ( cma ); titleLabel.addMouseMotionListener ( cma ); final WebPanel titlePanel = new WebPanel ( new BorderLayout ( 5, 0 ) ); titlePanel.setOpaque ( false ); titlePanel.setMargin ( 4, 5, 4, 10 ); titlePanel.add ( titleIcon, BorderLayout.LINE_START ); titlePanel.add ( titleLabel, BorderLayout.CENTER ); return titlePanel; } /** * */ protected class TitleLabel extends WebLabel { /** * Returns window title text. * There is a small workaround to show window title even when it is empty. * That workaround allows window dragging even when title is not set. * * @return window title text */ @Override public String getText () { final String title = getWindowTitle (); return title != null && !title.equals ( "" ) ? title : emptyTitleText; } /** * Returns preferred title size. * There is also a predefined title width limit to force it shrink. * * @return preferred title size */ @Override public Dimension getPreferredSize () { final Dimension ps = super.getPreferredSize (); ps.width = Math.min ( ps.width, maxTitleWidth ); return ps; } /** * Returns actual preferred size of the title label. * * @return actual preferred size of the title label */ public Dimension getRequiredSize () { return super.getPreferredSize (); } } protected void updateButtons () { // Removing old buttons if ( windowButtons != null ) { root.remove ( windowButtons ); } // Creating new buttons final boolean isFrame = isFrame (); final JComponent[] buttons = new JComponent[ 3 ]; if ( showMinimizeButton && isFrame ) { final WebButton minimize = new WebButton ( minimizeIcon ); minimize.setName ( "minimize" ); minimize.setRolloverIcon ( minimizeActiveIcon ); minimize.addActionListener ( new ActionListener () { @Override public void actionPerformed ( final ActionEvent e ) { iconify (); } } ); buttons[ 0 ] = minimize; } if ( showMaximizeButton && isResizable () && isFrame ) { final WebButton maximize = new WebButton ( maximizeIcon ) { @Override public Icon getIcon () { return isFrameMaximized () ? restoreIcon : maximizeIcon; } @Override public Icon getRolloverIcon () { return isFrameMaximized () ? restoreActiveIcon : maximizeActiveIcon; } }; maximize.setName ( "maximize" ); maximize.setRolloverIcon ( maximizeActiveIcon ); maximize.addActionListener ( new ActionListener () { @Override public void actionPerformed ( final ActionEvent e ) { if ( isFrame () ) { if ( isFrameMaximized () ) { restore (); } else { maximize (); } } } } ); buttons[ 1 ] = maximize; } if ( showCloseButton ) { final WebButton close = new WebButton ( closeIcon ); close.setName ( "close" ); close.setRolloverIcon ( closeActiveIcon ); close.addActionListener ( new ActionListener () { @Override public void actionPerformed ( final ActionEvent e ) { close (); } } ); buttons[ 2 ] = close; } windowButtons = new WebButtonGroup ( buttons ) { @Override public void updateButtonsStyling () { if ( groupButtons ) { super.updateButtonsStyling (); } } }; updateWindowButtonsStyle (); root.add ( windowButtons ); } protected void updateWindowButtonsStyle () { if ( windowButtons != null ) { windowButtons.setButtonsDrawFocus ( false ); windowButtons.setButtonsShadeWidth ( WebRootPaneStyle.buttonsShadeWidth ); windowButtons.setButtonsRound ( round ); windowButtons.setButtonsMargin ( WebRootPaneStyle.buttonsMargin ); if ( attachButtons ) { windowButtons.setButtonsDrawTop ( false ); windowButtons.setButtonsDrawRight ( round > 0 ); } } } protected void uninstallDecorationComponents () { // Title if ( titleComponent != null ) { root.remove ( titleComponent ); titleComponent = null; } // Buttons if ( windowButtons != null ) { root.remove ( windowButtons ); windowButtons = null; } // Resize corner if ( resizeCorner != null ) { root.remove ( resizeCorner ); resizeCorner = null; } } /** * Returns window title */ protected String getWindowTitle () { if ( isDialog () ) { return dialog.getTitle (); } else if ( isFrame () ) { return frame.getTitle (); } else { return null; } } /** * Finds a frame image with most suitable size */ protected ImageIcon getWindowIcon () { final List images = window != null ? window.getIconImages () : null; if ( images != null && images.size () > 1 ) { int bestIndex = 0; int bestDiff = Math.abs ( images.get ( bestIndex ).getWidth ( null ) - 16 ); for ( int i = 1; i < images.size (); i++ ) { if ( bestDiff == 0 ) { break; } final int diff = Math.abs ( images.get ( i ).getWidth ( null ) - 16 ); if ( diff < bestDiff ) { bestIndex = i; bestDiff = diff; } } return generateProperIcon ( images.get ( bestIndex ) ); } else if ( images != null && images.size () == 1 ) { return generateProperIcon ( images.get ( 0 ) ); } else { return new ImageIcon (); } } protected ImageIcon generateProperIcon ( final Image image ) { if ( image.getWidth ( null ) <= 16 ) { return new ImageIcon ( image ); } else { return ImageUtils.createPreviewIcon ( image, 16 ); } } /** * Closes the Window. */ protected void close () { if ( window != null ) { window.dispatchEvent ( new WindowEvent ( window, WindowEvent.WINDOW_CLOSING ) ); } } /** * Iconifies the Frame. */ protected void iconify () { if ( frame != null ) { frame.setExtendedState ( Frame.ICONIFIED ); } } /** * Maximizes the Frame. */ protected void maximize () { if ( frame != null ) { frame.setExtendedState ( Frame.MAXIMIZED_BOTH ); } } /** * Restores the Frame size. */ protected void restore () { if ( frame != null ) { frame.setExtendedState ( Frame.NORMAL ); } } /** * Checks if root pane's window is resizable */ protected boolean isResizable () { return isDialog () ? dialog.isResizable () : isFrame () && frame.isResizable (); } /** * Checks if root pane is inside a frame */ protected boolean isFrame () { return frame != null; } /** * Checks if frame is maximized */ protected boolean isFrameMaximized () { return isFrame () && state == Frame.MAXIMIZED_BOTH; } /** * Checks if root pane is inside a dialog */ protected boolean isDialog () { return dialog != null; } /** * Custom window decoration */ @Override public void paint ( final Graphics g, final JComponent c ) { if ( styled ) { final Graphics2D g2d = ( Graphics2D ) g; final Object aa = GraphicsUtils.setupAntialias ( g2d ); final boolean max = isFrameMaximized (); if ( max ) { // Background g2d.setPaint ( new GradientPaint ( 0, 0, topBg, 0, 30, middleBg ) ); g2d.fillRect ( 0, 0, c.getWidth (), c.getHeight () ); // Border g2d.setPaint ( borderColor ); g2d.drawRect ( 0, 0, c.getWidth () - 1, c.getHeight () - 1 ); g2d.setPaint ( innerBorderColor ); g2d.drawRect ( 1, 1, c.getWidth () - 3, c.getHeight () - 3 ); // Watermark if ( drawWatermark ) { final Shape old = GraphicsUtils.intersectClip ( g2d, getWatermarkClip ( c ) ); g2d.drawImage ( getWatermark ().getImage (), 2, 2, null ); GraphicsUtils.restoreClip ( g2d, old ); } } else { // Shade if ( shadeWidth > 0 ) { final int diff = isActive ( c ) ? 0 : shadeWidth - inactiveShadeWidth; getShadeIcon ( c ).paintIcon ( g2d, diff, diff, c.getWidth () - diff * 2, c.getHeight () - diff * 2 ); } // Background g2d.setPaint ( new GradientPaint ( 0, shadeWidth, topBg, 0, shadeWidth + 30, middleBg ) ); g2d.fillRoundRect ( shadeWidth, shadeWidth, c.getWidth () - shadeWidth * 2, c.getHeight () - shadeWidth * 2, round * 2, round * 2 ); // Border g2d.setPaint ( borderColor ); g2d.drawRoundRect ( shadeWidth, shadeWidth, c.getWidth () - shadeWidth * 2 - 1, c.getHeight () - shadeWidth * 2 - 1, round * 2 - 2, round * 2 - 2 ); g2d.setPaint ( innerBorderColor ); g2d.drawRoundRect ( shadeWidth + 1, shadeWidth + 1, c.getWidth () - shadeWidth * 2 - 3, c.getHeight () - shadeWidth * 2 - 3, round * 2 - 4, round * 2 - 4 ); // Watermark if ( drawWatermark ) { final Shape old = GraphicsUtils.intersectClip ( g2d, getWatermarkClip ( c ) ); g2d.drawImage ( getWatermark ().getImage (), shadeWidth + 2, shadeWidth + 2, null ); GraphicsUtils.restoreClip ( g2d, old ); } } GraphicsUtils.restoreAntialias ( g2d, aa ); } } protected RoundRectangle2D.Double getWatermarkClip ( final JComponent c ) { return new RoundRectangle2D.Double ( shadeWidth + 2, shadeWidth + 2, c.getWidth () - shadeWidth * 2 - 3, c.getHeight () - shadeWidth * 2 - 3, round * 2 - 4, round * 2 - 4 ); } protected NinePatchIcon getShadeIcon ( final JComponent c ) { if ( shadeWidth > 0 ) { return NinePatchUtils.getShadeIcon ( getShadeWidth ( c ), round, 0.8f ); } else { return null; } } protected int getShadeWidth ( final JComponent c ) { return isActive ( c ) ? shadeWidth : inactiveShadeWidth; } protected boolean isActive ( final JComponent c ) { return SwingUtils.getWindowAncestor ( c ).isFocused (); } }