Textured Tool Bar Sample Code
This sample program simulates the appearance of the tool bars in the Mail and TextEdit applications.
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import javax.swing.*;
import org.jetbrains.annotations.*;
/**
* Sample program for textured tool bars. The application specific icons are not included!
*/
public class ToolbarSampleProgram
{
public final static int POSITION_FIRST = 0;
public final static int POSITION_MIDDLE = 1;
public final static int POSITION_LAST = 2;
public final static int POSITION_ONLY = 3;
protected final Icon defaultIcon = createDefaultIcon();
public ToolbarSampleProgram()
{
{
MailFrame fr = new MailFrame();
fr.setBounds(50, 100, 800, 600);
fr.setVisible(true);
}
{
TextEditFrame fr = new TextEditFrame();
fr.setBounds(900, 200, 600, 600);
fr.setVisible(true);
}
}
protected class SampleToolbarFrame
extends JFrame
{
public SampleToolbarFrame(@NotNull JToolBar toolBar)
{
JRootPane rootPane = getRootPane();
rootPane.putClientProperty("Aqua.windowStyle", "unifiedToolBar");
setLayout(new BorderLayout());
add(toolBar, BorderLayout.NORTH);
}
}
protected class MailFrame
extends SampleToolbarFrame
{
private final JPanel p;
public MailFrame()
{
super(new MailToolbar("regular"));
p = new JPanel();
p.setFocusable(true);
add(p);
}
@Override
public void addNotify()
{
super.addNotify();
p.requestFocusInWindow();
}
}
protected class TextEditFrame
extends SampleToolbarFrame
{
private final JTextPane p;
public TextEditFrame()
{
super(new TextEditToolbar("mini"));
p = new JTextPane();
add(p);
}
@Override
public void addNotify()
{
super.addNotify();
p.requestFocusInWindow();
}
}
protected class MailToolbar
extends JToolBar
{
public MailToolbar(@NotNull String sizeVariant)
{
add(new MyMailRow(sizeVariant));
}
}
protected class TextEditToolbar
extends JToolBar
{
public TextEditToolbar(@NotNull String sizeVariant)
{
add(new MyTextEditRow(sizeVariant));
}
}
protected class RowPaneBase
extends JPanel
{
protected GroupLayout.SequentialGroup hGroup;
protected GroupLayout.ParallelGroup vGroup;
protected RowPaneBase()
{
setOpaque(false);
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
hGroup = layout.createSequentialGroup();
vGroup = layout.createParallelGroup();
layout.setHorizontalGroup(hGroup);
layout.setVerticalGroup(vGroup);
}
protected void add(@NotNull JComponent c)
{
hGroup.addComponent(c, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
vGroup.addComponent(c);
}
protected void add(@NotNull JComponent c, int width)
{
hGroup.addComponent(c, width, width, width);
vGroup.addComponent(c);
}
protected void addExpandingGap()
{
hGroup.addGap(0, 10, 10000);
vGroup.addGap(0);
}
protected void addGap(int width)
{
hGroup.addGap(width, width, width);
vGroup.addGap(0);
}
}
protected abstract class RowBase
extends RowPaneBase
{
protected final @NotNull String sizeVariant;
private final int buttonWidth = 41;
private final int iconSize;
private final float sizeFudge;
protected RowBase(@NotNull String sizeVariant)
{
this.sizeVariant = sizeVariant;
iconSize = determineIconSize();
sizeFudge = determineSizeFudge();
}
protected int determineIconSize()
{
if (sizeVariant.equals("small")) {
return 13;
} else if (sizeVariant.equals("mini")) {
return 11;
} else {
return 15;
}
}
protected float determineSizeFudge()
{
// assumes sizes are based on "regular"
if (sizeVariant.equals("small")) {
return 0.85f;
} else if (sizeVariant.equals("mini")) {
return 0.75f;
} else {
return 1;
}
}
@Override
protected void add(@NotNull JComponent c, int width)
{
width = (int) (width * sizeFudge);
c.setMinimumSize(new Dimension(width, 0));
c.setMaximumSize(new Dimension(width, 1000));
super.add(c, width);
}
protected AbstractButton createPushButton(@NotNull Icon icon)
{
return createSegmentedButton(icon, POSITION_ONLY);
}
protected AbstractButton createPushButton(@NotNull String label)
{
return createSegmentedButton(label, POSITION_ONLY);
}
protected AbstractButton createToggleButton(@NotNull Icon icon)
{
return createSegmentedToggleButton(icon, POSITION_ONLY);
}
protected AbstractButton createToggleButton(@NotNull String label)
{
return createSegmentedToggleButton(label, POSITION_ONLY);
}
protected AbstractButton createSegmentedButton(@NotNull Icon icon, int position)
{
JButton b = new JButton(icon);
b.putClientProperty("JButton.buttonType", "segmented");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected AbstractButton createSegmentedButton(@NotNull String label, int position)
{
JButton b = new JButton(label);
b.putClientProperty("JButton.buttonType", "segmented");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected AbstractButton createSegmentedToggleButton(@NotNull Icon icon, int position)
{
JToggleButton b = new JToggleButton(icon);
b.putClientProperty("JButton.buttonType", "segmented");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected AbstractButton createSegmentedToggleButton(@NotNull String label, int position)
{
JToggleButton b = new JToggleButton(label);
b.putClientProperty("JButton.buttonType", "segmented");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected AbstractButton createSegmentedColorButton(@NotNull String label, int position, @Nullable Color color)
{
JButton b = new ColorButton(label, color);
b.putClientProperty("JButton.buttonType", "segmented");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected AbstractButton createSeparatedButton(@NotNull Icon icon, int position)
{
JButton b = new JButton(icon);
b.putClientProperty("JButton.buttonType", "segmentedSeparated");
b.putClientProperty("JButton.segmentPosition", toPosition(position));
return setup(b);
}
protected JComboBox createPullDownButton(@NotNull String label)
{
JComboBox b = new JComboBox();
b.setEditable(false);
b.putClientProperty("JComponent.sizeVariant", sizeVariant);
b.putClientProperty("JComboBox.isPopDown", true);
b.putClientProperty("JComboBox.title", label);
return b;
}
protected JComboBox createPullDownButton(@NotNull Icon icon)
{
JComboBox b = new JComboBox();
b.setEditable(false);
b.putClientProperty("JComponent.sizeVariant", sizeVariant);
b.putClientProperty("JComboBox.isPopDown", true);
b.putClientProperty("JComboBox.title", icon);
return b;
}
protected JComboBox createPopUpButton()
{
JComboBox b = new JComboBox();
b.setEditable(false);
b.putClientProperty("JComponent.sizeVariant", sizeVariant);
return b;
}
protected JComboBox createComboBox()
{
JComboBox b = new JComboBox();
b.setEditable(true);
b.putClientProperty("JComponent.sizeVariant", sizeVariant);
return b;
}
protected JTextField createTextField()
{
JTextField t = new JTextField();
t.putClientProperty("JComponent.sizeVariant", sizeVariant);
return t;
}
protected JTextField createSearchField()
{
JTextField t = new JTextField();
t.putClientProperty("JComponent.sizeVariant", sizeVariant);
t.putClientProperty("JTextField.style", "search");
return t;
}
protected AbstractButton setup(@NotNull AbstractButton b)
{
b.putClientProperty("JComponent.sizeVariant", sizeVariant);
if (!b.isMinimumSizeSet()) {
b.setMinimumSize(new Dimension(buttonWidth, 0));
}
return b;
}
protected @NotNull Icon getIcon(@NotNull String name)
{
return adjustIcon(defaultIcon);
}
protected @NotNull Icon adjustIcon(@NotNull Icon ic)
{
if (ic instanceof ImageIcon) {
ImageIcon ii = (ImageIcon) ic;
double sx = (1.3 * iconSize * sizeFudge) / ic.getIconWidth();
double sy = (1.0 * iconSize * sizeFudge) / ic.getIconHeight();
double s = Math.min(sx, sy);
int width = (int) (ic.getIconWidth() * s);
int height = (int) (ic.getIconHeight() * s);
return new ImageIcon(ii.getImage().getScaledInstance(width, height, 0));
} else {
return ic;
}
}
}
/**
A row of components that simulates the contents of the Mail toolbar. Mail uses regular size.
*/
protected class MyMailRow
extends RowBase
{
private AbstractButton getMailButton;
private AbstractButton composeButton;
private AbstractButton archiveButton;
private AbstractButton trashButton;
private AbstractButton junkButton;
private AbstractButton replyButton;
private AbstractButton replyAllButton;
private AbstractButton forwardButton;
private AbstractButton flagButton;
private AbstractButton flagMenuButton;
private JTextField searchField;
public MyMailRow(@NotNull String sizeVariant)
{
super(sizeVariant);
getMailButton = createPushButton(getIcon("GetMailTemplate"));
composeButton = createPushButton(getIcon("ComposeTemplate"));
archiveButton = createPushButton(getIcon("ArchiveTemplate"));
trashButton = createSegmentedButton(getIcon("TrashTemplate"), POSITION_FIRST);
junkButton = createSegmentedButton(getIcon("JunkTemplate"), POSITION_LAST);
replyButton = createSegmentedButton(getIcon("ReplyTemplate"), POSITION_FIRST);
replyAllButton = createSegmentedButton(getIcon("ReplyAllTemplate"), POSITION_MIDDLE);
forwardButton = createSegmentedButton(getIcon("ForwardTemplate"), POSITION_LAST);
flagButton = createSegmentedButton(getIcon("Flag"), POSITION_FIRST);
flagMenuButton = createSegmentedButton(getIcon("DownMenuTemplate"), POSITION_LAST);
searchField = createSearchField();
addGap(8);
add(getMailButton, 38);
addGap(8);
add(composeButton, 38);
addGap(82);
add(archiveButton, 38);
addGap(8);
add(trashButton, 36);
add(junkButton, 36);
addGap(8);
add(replyButton, 36);
add(replyAllButton, 35);
add(forwardButton, 36);
addGap(8);
add(flagButton, 27);
add(flagMenuButton, 15);
addExpandingGap();
add(searchField, 325);
addGap(8);
}
}
/**
A row of components that simulates the contents of the TextEdit toolbar. TextEdit uses mini size.
*/
protected class MyTextEditRow
extends RowBase
{
private JComboBox paragraphStyleMenuButton;
private JComboBox fontFamilyMenuButton;
private JComboBox typefaceMenuButton;
private JComboBox fontSizeSelector;
private AbstractButton textColorButton;
private AbstractButton textBackgroundColorButton;
private AbstractButton boldButton;
private AbstractButton italicButton;
private AbstractButton underlineButton;
private AbstractButton leftAlignButton;
private AbstractButton centerAlignButton;
private AbstractButton rightAlignButton;
private AbstractButton justifyButton;
private JComboBox spacingMenuButton;
private JComboBox listFormatMenuButton;
public MyTextEditRow(@NotNull String sizeVariant)
{
super(sizeVariant);
paragraphStyleMenuButton = createPullDownButton("\u00B6");
fontFamilyMenuButton = createPopUpButton();
typefaceMenuButton = createPopUpButton();
fontSizeSelector = createComboBox();
textColorButton = createSegmentedColorButton("", POSITION_ONLY, Color.BLACK);
textBackgroundColorButton = createSegmentedColorButton("a", POSITION_ONLY, null);
boldButton = createSegmentedToggleButton("B", POSITION_FIRST);
italicButton = createSegmentedToggleButton("I", POSITION_MIDDLE);
underlineButton = createSegmentedToggleButton("U", POSITION_LAST);
leftAlignButton = createSegmentedToggleButton(getIcon("LeftAlignTemplate"), POSITION_FIRST);
centerAlignButton = createSegmentedToggleButton(getIcon("CenterTemplate"), POSITION_MIDDLE);
rightAlignButton = createSegmentedToggleButton(getIcon("RightAlignTemplate"), POSITION_MIDDLE);
justifyButton = createSegmentedToggleButton(getIcon("JustifyTemplate"), POSITION_LAST);
spacingMenuButton = createPopUpButton();
listFormatMenuButton = createPullDownButton(getIcon("ListFormatTemplate"));
paragraphStyleMenuButton.setModel(createParagraphStyleModel());
fontFamilyMenuButton.setModel(createFontFamilyModel());
typefaceMenuButton.setModel(createTypeFaceModel());
fontSizeSelector.setModel(createFontSizeModel());
spacingMenuButton.setModel(createSpacingModel());
listFormatMenuButton.setModel(createListFormatModel());
boldButton.setSelected(true);
{
Font f = textBackgroundColorButton.getFont();
textBackgroundColorButton.setFont(f.deriveFont(f.getSize2D()+4).deriveFont(Font.BOLD));
}
{
int size = getTypeSize();
boldButton.setFont(new Font("Baskerville", Font.BOLD, size));
italicButton.setFont(new Font("Baskerville", Font.BOLD + Font.ITALIC, size));
underlineButton.setFont(new Font("Baskerville", Font.PLAIN, size));
}
{
Color g = new Color(115, 115, 115);
boldButton.setForeground(g);
italicButton.setForeground(g);
underlineButton.setForeground(g);
italicButton.setEnabled(false);
}
{
ButtonGroup g = new ButtonGroup();
g.add(leftAlignButton);
g.add(centerAlignButton);
g.add(rightAlignButton);
g.add(justifyButton);
leftAlignButton.setSelected(true);
}
add(paragraphStyleMenuButton, 26);
addGap(6);
add(fontFamilyMenuButton, 99);
addGap(2);
add(typefaceMenuButton, 79);
addGap(2);
add(fontSizeSelector, 45);
addGap(6);
add(textColorButton, 23);
addGap(2);
add(textBackgroundColorButton, 23);
addGap(6);
add(boldButton, 18);
add(italicButton, 18);
add(underlineButton, 18);
addGap(6);
add(leftAlignButton, 18);
add(centerAlignButton, 18);
add(rightAlignButton, 18);
add(justifyButton, 18);
addGap(6);
add(spacingMenuButton, 38);
addGap(2);
add(listFormatMenuButton, 38);
}
protected int getTypeSize()
{
if (sizeVariant.equals("small")) {
return 15;
} else if (sizeVariant.equals("regular")) {
return 18;
} else {
return 13;
}
}
@Override
protected float determineSizeFudge()
{
// sizes are based on "mini"
if (sizeVariant.equals("small")) {
return 1.15f;
} else if (sizeVariant.equals("regular")) {
return 1.35f;
} else {
return 1;
}
}
}
private ComboBoxModel createParagraphStyleModel()
{
String[] items = { "Default", "Header" };
return new DefaultComboBoxModel<>(items);
}
private ComboBoxModel createFontFamilyModel()
{
String[] items = { "Lucida Grande", "Helvetica" };
return new DefaultComboBoxModel<>(items);
}
private ComboBoxModel createTypeFaceModel()
{
String[] items = { "Regular", "Bold" };
return new DefaultComboBoxModel<>(items);
}
private ComboBoxModel createFontSizeModel()
{
String[] items = { "9", "10", "11", "12", "13", "14", "18", "24", "36", "48", "64" };
return new DefaultComboBoxModel<>(items);
}
private ComboBoxModel createSpacingModel()
{
String[] items = { "0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5" };
ComboBoxModel model = new DefaultComboBoxModel<>(items);
model.setSelectedItem("1.0");
return model;
}
private ComboBoxModel createListFormatModel()
{
String[] items = { "None", "1. 2. 3..." };
return new DefaultComboBoxModel<>(items);
}
private class ColorButton
extends JButton
{
private @Nullable Color color;
public ColorButton(@NotNull String label, @Nullable Color color)
{
super(label);
this.color = color;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D gg = (Graphics2D) g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int x = 3;
int y = 3;
int right = getWidth() - 6;
int bottom = getHeight() - 8;
Shape s = new RoundRectangle2D.Double(x, y, right, bottom, 4, 4);
if (color == null) {
gg.setColor(Color.RED);
gg.drawLine(x+1, bottom+1, right+1, y+1);
} else {
gg.setColor(color);
gg.fill(s);
}
gg.setStroke(new BasicStroke(1));
gg.setColor(new Color(232, 232, 232));
gg.draw(s);
}
}
private @NotNull String toPosition(int position)
{
switch (position) {
case POSITION_FIRST:
return "first";
case POSITION_MIDDLE:
return "middle";
case POSITION_LAST:
return "last";
default:
return "only";
}
}
private Icon createDefaultIcon() {
String imageName = "NSImage://NSActionTemplate";
Image im = Toolkit.getDefaultToolkit().getImage(imageName);
if (im != null) {
return new ImageIcon(im);
}
System.err.println("Unable to load image: " + imageName);
return null;
}
}