org.pushingpixels.radiance.component.internal.ui.common.CommandButtonLayoutManagerTile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swingset3-demos Show documentation
Show all versions of swingset3-demos Show documentation
Demonstrating the abilities of the Swing UI Toolkit swingset2 and swingx aka swingset3
The newest version!
/*
* Copyright (c) 2005-2022 Radiance Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.radiance.component.internal.ui.common;
import org.pushingpixels.radiance.component.api.common.CommandButtonLayoutManager;
import org.pushingpixels.radiance.component.api.common.JCommandButton;
import org.pushingpixels.radiance.component.internal.utils.ComponentUtilities;
import org.pushingpixels.radiance.common.api.RadianceCommonCortex;
import org.jdesktop.swingx.icon.RadianceIcon;
import org.pushingpixels.radiance.theming.internal.utils.RadianceMetricsUtilities;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class CommandButtonLayoutManagerTile implements CommandButtonLayoutManager {
@Override
public int getPreferredIconSize(JCommandButton commandButton) {
return ComponentUtilities.getScaledSize(32, commandButton.getFont().getSize(), 2.0, 4);
}
@Override
public Dimension getPreferredSize(JCommandButton commandButton) {
Insets borderInsets = commandButton.getInsets();
int by = borderInsets.top + borderInsets.bottom;
FontMetrics fm = RadianceMetricsUtilities.getFontMetrics(
RadianceCommonCortex.getScaleFactor(commandButton), commandButton.getFont());
String buttonText = commandButton.getText();
int titleWidth = (buttonText == null) ? 0 : fm
.stringWidth(commandButton.getText());
String extraText = commandButton.getExtraText();
int extraWidth = (extraText == null) ? 0 : fm.stringWidth(extraText);
double textWidth = Math.max(titleWidth, extraWidth);
int layoutHGap = ComponentUtilities.getHLayoutGap(commandButton);
boolean hasIcon = (commandButton.getIcon() != null);
boolean hasText = (textWidth > 0);
boolean hasPopupIcon = ComponentUtilities.hasPopupAction(commandButton);
int prefIconSize = hasIcon ? this.getPreferredIconSize(commandButton) : 0;
// start with the left insets
int width = borderInsets.left;
// icon?
if (hasIcon) {
// padding before the icon
width += layoutHGap;
// icon width
width += prefIconSize;
// padding after the icon
width += layoutHGap;
}
// text?
if (hasText) {
// padding before the text
width += layoutHGap;
// text width
width += textWidth;
// padding after the text
width += layoutHGap;
}
// popup icon?
if (hasPopupIcon) {
// padding before the popup icon
width += 2 * layoutHGap;
// text width
width += 1 + fm.getHeight() / 2;
// padding after the popup icon
width += 2 * layoutHGap;
}
JCommandButton.CommandButtonKind buttonKind = commandButton.getCommandButtonKind();
boolean hasSeparator = false;
if (buttonKind == JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_ACTION
&& (hasIcon || hasText)) {
hasSeparator = true;
}
if (buttonKind == JCommandButton.CommandButtonKind.ACTION_AND_POPUP_MAIN_POPUP
&& hasIcon) {
hasSeparator = true;
}
if (hasSeparator) {
// space for a vertical separator
width += new JSeparator(JSeparator.VERTICAL).getPreferredSize().width;
}
// right insets
width += borderInsets.right;
// and remove the padding before the first and after the last elements
width -= 2 * layoutHGap;
return new Dimension(width,
by + Math.max(prefIconSize, 2 * (fm.getAscent() + fm.getDescent())));
}
@Override
public Point getActionKeyTipAnchorCenterPoint(JCommandButton commandButton) {
CommandButtonLayoutInfo layoutInfo = this.getLayoutInfo(commandButton);
boolean hasIcon = (commandButton.getIcon() != null);
int height = commandButton.getHeight();
if (commandButton.getComponentOrientation().isLeftToRight()) {
// If the button shows icon, the key tip is at the right edge of the icon
// otherwise it is at the right edge of the full action click area
int x = hasIcon ? layoutInfo.iconRect.x + layoutInfo.iconRect.width
: layoutInfo.actionClickArea.x + layoutInfo.actionClickArea.width;
return new Point(x, (height + layoutInfo.actionClickArea.height) / 2);
} else {
// If the button shows icon, the key tip is at the left edge of the icon
// otherwise it is at the left edge of the full action click area
int x = hasIcon ? layoutInfo.iconRect.x : layoutInfo.actionClickArea.x;
return new Point(x, (height + layoutInfo.actionClickArea.height) / 2);
}
}
@Override
public Point getPopupKeyTipAnchorCenterPoint(JCommandButton commandButton) {
CommandButtonLayoutInfo layoutInfo = this.getLayoutInfo(commandButton);
int height = commandButton.getHeight();
if (commandButton.getComponentOrientation().isLeftToRight()) {
return new Point(layoutInfo.popupClickArea.x + layoutInfo.popupClickArea.width,
(height + layoutInfo.popupClickArea.height) / 2);
} else {
return new Point(layoutInfo.popupClickArea.x,
(height + layoutInfo.popupClickArea.height) / 2);
}
}
@Override
public CommandButtonLayoutInfo getLayoutInfo(JCommandButton commandButton) {
CommandButtonLayoutInfo result = new CommandButtonLayoutInfo();
result.actionClickArea = new Rectangle(0, 0, 0, 0);
result.popupClickArea = new Rectangle(0, 0, 0, 0);
Insets ins = commandButton.getInsets();
result.iconRect = new Rectangle();
result.popupActionRect = new Rectangle();
boolean ltr = commandButton.getComponentOrientation().isLeftToRight();
int width = commandButton.getWidth();
int height = commandButton.getHeight();
int prefWidth = this.getPreferredSize(commandButton).width;
int shiftX = 0;
if (width > prefWidth) {
// We have more horizontal space than needed to display the content.
// Consult the horizontal alignment attribute of the command button to see
// how we should shift the content horizontally.
switch (commandButton.getHorizontalAlignment()) {
case SwingConstants.LEADING:
break;
case SwingConstants.CENTER:
// shift everything to be centered horizontally
shiftX = (width - prefWidth) / 2;
break;
case SwingConstants.TRAILING:
// shift everything to the end of the button bounds
shiftX = width - prefWidth;
}
}
RadianceIcon buttonIcon = commandButton.getIcon();
String buttonText = commandButton.getText();
String buttonExtraText = commandButton.getExtraText();
boolean hasIcon = (buttonIcon != null);
boolean hasText = (buttonText != null) || (buttonExtraText != null);
boolean hasPopupIcon = ComponentUtilities.hasPopupAction(commandButton);
FontMetrics fm = RadianceMetricsUtilities.getFontMetrics(
RadianceCommonCortex.getScaleFactor(commandButton), commandButton.getFont());
int labelHeight = fm.getAscent() + fm.getDescent();
JCommandButton.CommandButtonKind buttonKind = commandButton.getCommandButtonKind();
int layoutHGap = ComponentUtilities.getHLayoutGap(commandButton);
if (ltr) {
int x = ins.left + shiftX - layoutHGap;
// icon
if (hasIcon) {
x += layoutHGap;
int iconHeight = buttonIcon.getIconHeight();
int iconWidth = buttonIcon.getIconWidth();
result.iconRect.x = x;
result.iconRect.y = (height - iconHeight) / 2;
result.iconRect.width = iconWidth;
result.iconRect.height = iconHeight;
x += (iconWidth + layoutHGap);
}
// text
if (hasText) {
x += layoutHGap;
TextLayoutInfo lineLayoutInfo = new TextLayoutInfo();
lineLayoutInfo.text = commandButton.getText();
lineLayoutInfo.textRect = new Rectangle();
lineLayoutInfo.textRect.x = x;
lineLayoutInfo.textRect.y = (height - 2 * labelHeight) / 2;
lineLayoutInfo.textRect.width = (buttonText == null) ? 0
: fm.stringWidth(buttonText);
lineLayoutInfo.textRect.height = labelHeight;
result.textLayoutInfoList = new ArrayList<>();
result.textLayoutInfoList.add(lineLayoutInfo);
String extraText = commandButton.getExtraText();
TextLayoutInfo extraLineLayoutInfo = new TextLayoutInfo();
extraLineLayoutInfo.text = extraText;
extraLineLayoutInfo.textRect = new Rectangle();
extraLineLayoutInfo.textRect.x = x;
extraLineLayoutInfo.textRect.y = lineLayoutInfo.textRect.y
+ labelHeight;
extraLineLayoutInfo.textRect.width = (extraText == null) ? 0
: fm.stringWidth(extraText);
extraLineLayoutInfo.textRect.height = labelHeight;
result.extraTextLayoutInfoList = new ArrayList<>();
result.extraTextLayoutInfoList.add(extraLineLayoutInfo);
x += Math.max(lineLayoutInfo.textRect.width,
extraLineLayoutInfo.textRect.width);
x += layoutHGap;
}
if (hasPopupIcon) {
x += 2 * layoutHGap;
result.popupActionRect.x = x;
result.popupActionRect.y = (height - labelHeight) / 2 - 1;
result.popupActionRect.width = 1 + labelHeight / 2;
result.popupActionRect.height = labelHeight + 2;
x += result.popupActionRect.width;
x += 2 * layoutHGap;
}
int xBorderBetweenActionAndPopup = 0;
int verticalSeparatorWidth = new JSeparator(JSeparator.VERTICAL)
.getPreferredSize().width;
// compute the action and popup click areas
switch (buttonKind) {
case ACTION_ONLY:
result.actionClickArea.x = 0;
result.actionClickArea.y = 0;
result.actionClickArea.width = width;
result.actionClickArea.height = height;
result.isTextInActionArea = true;
break;
case POPUP_ONLY:
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
result.isTextInActionArea = false;
break;
case ACTION_AND_POPUP_MAIN_ACTION:
// 1. break before popup icon if button has text or icon
// 2. no break (all popup) if button has no text and no icon
if (hasText || hasIcon) {
// shift popup action rectangle to the right to
// accomodate the vertical separator
result.popupActionRect.x += verticalSeparatorWidth;
xBorderBetweenActionAndPopup = result.popupActionRect.x - 2
* layoutHGap;
result.actionClickArea.x = 0;
result.actionClickArea.y = 0;
result.actionClickArea.width = xBorderBetweenActionAndPopup;
result.actionClickArea.height = height;
result.popupClickArea.x = xBorderBetweenActionAndPopup;
result.popupClickArea.y = 0;
result.popupClickArea.width = width
- xBorderBetweenActionAndPopup;
result.popupClickArea.height = height;
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
result.separatorArea = new Rectangle();
result.separatorArea.x = xBorderBetweenActionAndPopup;
result.separatorArea.y = 0;
result.separatorArea.width = verticalSeparatorWidth;
result.separatorArea.height = height;
} else {
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
}
result.isTextInActionArea = true;
break;
case ACTION_AND_POPUP_MAIN_POPUP:
// 1. break after icon if button has icon
// 2. no break (all popup) if button has no icon
if (hasIcon) {
// shift text rectangles and popup action rectangle to the
// right
// to accomodate the vertical separator
if (result.textLayoutInfoList != null) {
for (TextLayoutInfo textLayoutInfo : result.textLayoutInfoList) {
textLayoutInfo.textRect.x += verticalSeparatorWidth;
}
}
if (result.extraTextLayoutInfoList != null) {
for (TextLayoutInfo extraTextLayoutInfo : result.extraTextLayoutInfoList) {
extraTextLayoutInfo.textRect.x += verticalSeparatorWidth;
}
}
result.popupActionRect.x += verticalSeparatorWidth;
xBorderBetweenActionAndPopup = result.iconRect.x
+ result.iconRect.width + layoutHGap;
result.actionClickArea.x = 0;
result.actionClickArea.y = 0;
result.actionClickArea.width = xBorderBetweenActionAndPopup;
result.actionClickArea.height = height;
result.popupClickArea.x = xBorderBetweenActionAndPopup;
result.popupClickArea.y = 0;
result.popupClickArea.width = width
- xBorderBetweenActionAndPopup;
result.popupClickArea.height = height;
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
result.separatorArea = new Rectangle();
result.separatorArea.x = xBorderBetweenActionAndPopup;
result.separatorArea.y = 0;
result.separatorArea.width = verticalSeparatorWidth;
result.separatorArea.height = height;
} else {
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
}
result.isTextInActionArea = false;
break;
}
} else {
int x = width - ins.right - shiftX + layoutHGap;
// icon
if (hasIcon) {
x -= layoutHGap;
int iconHeight = buttonIcon.getIconHeight();
int iconWidth = buttonIcon.getIconWidth();
result.iconRect.x = x - iconWidth;
result.iconRect.y = (height - iconHeight) / 2;
result.iconRect.width = iconWidth;
result.iconRect.height = iconHeight;
x -= (iconWidth + layoutHGap);
}
// text
if (hasText) {
x -= layoutHGap;
TextLayoutInfo lineLayoutInfo = new TextLayoutInfo();
lineLayoutInfo.text = commandButton.getText();
lineLayoutInfo.textRect = new Rectangle();
lineLayoutInfo.textRect.width = (buttonText == null) ? 0
: fm.stringWidth(buttonText);
lineLayoutInfo.textRect.x = x - lineLayoutInfo.textRect.width;
lineLayoutInfo.textRect.y = (height - 2 * labelHeight) / 2;
lineLayoutInfo.textRect.height = labelHeight;
result.textLayoutInfoList = new ArrayList<>();
result.textLayoutInfoList.add(lineLayoutInfo);
String extraText = commandButton.getExtraText();
TextLayoutInfo extraLineLayoutInfo = new TextLayoutInfo();
extraLineLayoutInfo.text = extraText;
extraLineLayoutInfo.textRect = new Rectangle();
extraLineLayoutInfo.textRect.width = (extraText == null) ? 0
: fm.stringWidth(extraText);
extraLineLayoutInfo.textRect.x = x
- extraLineLayoutInfo.textRect.width;
extraLineLayoutInfo.textRect.y = lineLayoutInfo.textRect.y
+ labelHeight;
extraLineLayoutInfo.textRect.height = labelHeight;
result.extraTextLayoutInfoList = new ArrayList<>();
result.extraTextLayoutInfoList.add(extraLineLayoutInfo);
x -= Math.max(lineLayoutInfo.textRect.width,
extraLineLayoutInfo.textRect.width);
x -= layoutHGap;
}
if (hasPopupIcon) {
x -= 2 * layoutHGap;
result.popupActionRect.width = 1 + labelHeight / 2;
result.popupActionRect.x = x - result.popupActionRect.width;
result.popupActionRect.y = (height - labelHeight) / 2 - 1;
result.popupActionRect.height = labelHeight + 2;
x -= result.popupActionRect.width;
x -= 2 * layoutHGap;
}
int xBorderBetweenActionAndPopup = 0;
int verticalSeparatorWidth = new JSeparator(JSeparator.VERTICAL)
.getPreferredSize().width;
// compute the action and popup click areas
switch (buttonKind) {
case ACTION_ONLY:
result.actionClickArea.x = 0;
result.actionClickArea.y = 0;
result.actionClickArea.width = width;
result.actionClickArea.height = height;
result.isTextInActionArea = true;
break;
case POPUP_ONLY:
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
result.isTextInActionArea = false;
break;
case ACTION_AND_POPUP_MAIN_ACTION:
// 1. break before popup icon if button has text or icon
// 2. no break (all popup) if button has no text and no icon
if (hasText || hasIcon) {
// shift popup action rectangle to the left to
// accomodate the vertical separator
result.popupActionRect.x -= verticalSeparatorWidth;
xBorderBetweenActionAndPopup = result.popupActionRect.x
+ result.popupActionRect.width + 2 * layoutHGap;
result.actionClickArea.x = xBorderBetweenActionAndPopup;
result.actionClickArea.y = 0;
result.actionClickArea.width = width
- xBorderBetweenActionAndPopup;
result.actionClickArea.height = height;
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = xBorderBetweenActionAndPopup;
result.popupClickArea.height = height;
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
result.separatorArea = new Rectangle();
result.separatorArea.x = xBorderBetweenActionAndPopup;
result.separatorArea.y = 0;
result.separatorArea.width = verticalSeparatorWidth;
result.separatorArea.height = height;
} else {
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
}
result.isTextInActionArea = true;
break;
case ACTION_AND_POPUP_MAIN_POPUP:
// 1. break after icon if button has icon
// 2. no break (all popup) if button has no icon
if (hasIcon) {
// shift text rectangles and popup action rectangle to the
// left to accomodate the vertical separator
if (result.textLayoutInfoList != null) {
for (TextLayoutInfo textLayoutInfo : result.textLayoutInfoList) {
textLayoutInfo.textRect.x -= verticalSeparatorWidth;
}
}
if (result.extraTextLayoutInfoList != null) {
for (TextLayoutInfo extraTextLayoutInfo : result.extraTextLayoutInfoList) {
extraTextLayoutInfo.textRect.x -= verticalSeparatorWidth;
}
}
result.popupActionRect.x -= verticalSeparatorWidth;
xBorderBetweenActionAndPopup = result.iconRect.x
- layoutHGap;
result.actionClickArea.x = xBorderBetweenActionAndPopup;
result.actionClickArea.y = 0;
result.actionClickArea.width = width
- xBorderBetweenActionAndPopup;
result.actionClickArea.height = height;
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = xBorderBetweenActionAndPopup;
result.popupClickArea.height = height;
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
result.separatorArea = new Rectangle();
result.separatorArea.x = xBorderBetweenActionAndPopup;
result.separatorArea.y = 0;
result.separatorArea.width = verticalSeparatorWidth;
result.separatorArea.height = height;
} else {
result.popupClickArea.x = 0;
result.popupClickArea.y = 0;
result.popupClickArea.width = width;
result.popupClickArea.height = height;
}
result.isTextInActionArea = false;
break;
}
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy