/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.uitools.swing;
import java.awt.Component;
import java.awt.Graphics;
import java.io.Serializable;
import java.util.List;
import java.util.Locale;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleIcon;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleStateSet;
import javax.swing.Icon;
import javax.swing.SwingConstants;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
/**
* This composite icon is just that: It allows clients to treat
* a group of icons as a single icon.
*/
public class CompositeIcon
implements Icon, Cloneable, Serializable, Accessible, SwingConstants
{
/**
* The icons to be painted together as a single icon.
* The icons will be painted in the order in which they are stored
* in this array and separated by the gaps stored in the array below.
* Null icons are allowed.
*/
Icon[] icons;
/**
* The gaps, in pixels, between the icons. A gap can be negative,
* which may result in the icons on either side of the gap overlapping
* each other. The number of gaps must be one less than the
* number of icons.
*/
private int[] gaps;
/**
* The orientation of the icons. A setting of HORIZONTAL will cause
* the icons to be painted starting at the "leading" edge of the canvas,
* which is determined the component's orientation ("left-to-right" or
* "right-to-left"). A setting of VERTICAL will cause the icons to be
* painted starting at the top of the canvas.
* The default orientation is HORIZONTAL.
* @see javax.swing.SwingConstants
*/
private int orientation;
public static final int[] VALID_ORIENTATION_VALUES = new int[] {HORIZONTAL, VERTICAL};
/**
* The alignment of the icons. If the orientation is HORIZONTAL,
* the alignment can be CENTER, TOP, or BOTTOM. If the orientation
* is VERTICAL, the alignment can be CENTER, LEADING, or TRAILING.
* For example, if the orientation is HORIZONTAL and the alignment
* is BOTTOM, the icons will be drawn horizontally with their bottom
* edges aligned.
* The default alignment is CENTER.
* @see javax.swing.SwingConstants
*/
private int alignment;
public static final int[] VALID_HORIZONTAL_ALIGNMENT_VALUES = new int[] {CENTER, TOP, BOTTOM};
public static final int[] VALID_VERTICAL_ALIGNMENT_VALUES = new int[] {CENTER, LEADING, TRAILING};
/**
* Whether the icons are always painted from left to right or the LEADING
* edge is always on the left, ignoring the component's orientation.
* If the override is true, the component's orientation is ignored and a
* HORIZONTAL orientation will always paint the icons from left to right
* and a VERTICAL orientation will always it LEADING edge on the left.
* This allows explicit control of the icon's appearance across locales.
* The default override is false.
*/
private boolean overrideLeftToRight;
/**
* A brief textual description of the icon used for accessibility.
*/
private String description;
/**
* Accessibility information for the composite icon.
*/
private AccessibleContext accessibleContext;
private static final Icon[] EMPTY_ICONS = new Icon[0];
private static final int[] EMPTY_GAPS = new int[0];
private static final long serialVersionUID = 1L;
// ********** constructors **********
/**
* Construct a composite icon with the specified
* and icons, gaps, and settings.
*/
public CompositeIcon(Icon[] icons, int[] gaps, int orientation, int alignment, String description) {
super();
if (icons.length == 0) {
if (gaps.length != 0) {
throw new IllegalArgumentException("if there are no icons, there can be no gaps either");
}
} else {
if (gaps.length != icons.length - 1) {
throw new IllegalArgumentException("if there are icons, there must be 1 fewer gaps than icons");
}
}
this.icons = icons;
this.gaps = gaps;
this.checkOrientation(orientation);
this.orientation = orientation;
this.setAlignment(alignment);
this.overrideLeftToRight = false; // default
this.setDescription(description);
}
/**
* Construct a composite icon with the specified icons and gaps
* and the default settings.
*/
public CompositeIcon(Icon[] icons, int[] gaps) {
this(icons, gaps, HORIZONTAL, CENTER, null);
}
/**
* Construct a composite icon with no icons or gaps
* and the default settings.
*/
public CompositeIcon() {
this(EMPTY_ICONS, EMPTY_GAPS);
}
/**
* Construct a composite icon with a single icon
* and the default settings.
*/
public CompositeIcon(Icon icon) {
this(new Icon[] {icon}, EMPTY_GAPS);
}
/**
* Construct a composite icon with default settings and
* the two specified icons with the specified gap between them.
*/
public CompositeIcon(Icon icon1, int gap, Icon icon2) {
this(new Icon[] {icon1, icon2}, new int[] {gap});
}
/**
* Construct a composite icon with default settings and
* the two specified icons with no gap between them.
*/
public CompositeIcon(Icon icon1, Icon icon2) {
this(icon1, 0, icon2);
}
/**
* Construct a composite icon with default settings and
* the specified icons with the specified fixed gap between them all.
*/
public CompositeIcon(Icon[] icons, int gap) {
this(icons, buildFixedGapsFor(icons.length, gap));
}
/**
* Construct a composite icon with default settings and
* the specified icons with no gaps between them.
*/
public CompositeIcon(Icon[] icons) {
this(icons, 0);
}
/**
* Construct a composite icon with default settings and
* the specified icons with no gaps between them.
*/
public CompositeIcon(List icons, int gap) {
this((Icon[]) icons.toArray(new Icon[icons.size()]), gap);
}
/**
* Construct a composite icon with default settings and
* the specified icons with no gaps between them.
*/
public CompositeIcon(List icons) {
this(icons, 0);
}
// ********** Icon implementation **********
/**
* HORIZONTAL: Add up all the widths and gaps
* (handling negative gaps appropriately).
* VERTICAL: The width of the widest icon.
* @see javax.swing.Icon#getIconWidth()
*/
public int getIconWidth() {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
if (this.orientation == HORIZONTAL) {
int[] localGaps = this.gaps;
int position = 0;
int min = 0;
int max = 0;
int gapsLength = localGaps.length;
// this loop MUST ascend
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position += icon.getIconWidth();
max = (max >= position) ? max : position;
}
if (i < gapsLength) {
position += localGaps[i];
max = (max >= position) ? max : position;
min = (min <= position) ? min : position;
}
}
return max - min;
}
// VERTICAL
int width = 0;
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
int iconWidth = icon.getIconWidth();
width = (width >= iconWidth) ? width : iconWidth;
}
}
return width;
}
/**
* VERTICAL: Add up all the heights and gaps.
* (handling negative gaps appropriately).
* HORIZONTAL: The height of the tallest icon.
* @see javax.swing.Icon#getIconHeight()
*/
public int getIconHeight() {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
if (this.orientation == VERTICAL) {
int[] localGaps = this.gaps;
int position = 0;
int min = 0;
int max = 0;
int gapsLength = localGaps.length;
// this loop MUST ascend
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position += icon.getIconHeight();
max = (max >= position) ? max : position;
}
if (i < gapsLength) {
position += localGaps[i];
max = (max >= position) ? max : position;
min = (min <= position) ? min : position;
}
}
return max - min;
}
// HORIZONTAL
int height = 0;
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
int iconHeight = icon.getIconHeight();
height = (height >= iconHeight) ? height : iconHeight;
}
}
return height;
}
/**
* @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics, int, int)
*/
public void paintIcon(Component component, Graphics g, int x, int y) {
if (this.orientation == HORIZONTAL) {
this.paintIconHorizontally(component, g, x, y);
} else { // VERTICAL
this.paintIconVertically(component, g, x, y);
}
}
private void paintIconHorizontally(Component component, Graphics g, int x, int y) {
if (this.isLeftToRight(component)) {
this.paintIconLeftToRight(component, g, x, y);
} else {
this.paintIconRightToLeft(component, g, x, y);
}
}
private void paintIconLeftToRight(Component component, Graphics g, int x, int y) {
switch (this.alignment) {
case CENTER:
this.paintIconLeftToRightCenterAligned(component, g, x, y);
break;
case TOP:
this.paintIconLeftToRightTopAligned(component, g, x, y);
break;
case BOTTOM:
this.paintIconLeftToRightBottomAligned(component, g, x, y);
break;
default:
throw new IllegalStateException("illegal alignment: " + this.alignment);
}
}
private void paintIconLeftToRightCenterAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the height of the composite icon so we can center the nested icons in it
int totalHeight = this.getIconHeight();
// start the sliding position on the left
int position = x + this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, position, y + ((totalHeight - icon.getIconHeight()) >> 1));
position += icon.getIconWidth();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
// one of our two most performant options :-)
private void paintIconLeftToRightTopAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// start the sliding position on the left
int position = x + this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, position, y);
position += icon.getIconWidth();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
private void paintIconLeftToRightBottomAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the bottom of the composite icon so we can position the nested icons there
int bottom = y + this.getIconHeight();
// start the sliding position on the left
int position = x + this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, position, bottom - icon.getIconHeight());
position += icon.getIconWidth();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
/**
* typically, the offset is zero; but it can be non-zero if
* there are any excessively negative gaps
*/
private int calculateHorizontalStartOffset() {
Icon[] localIcons = this.icons;
int[] localGaps = this.gaps;
int position = 0;
int min = 0;
int gapsLength = localGaps.length;
// this loop MUST ascend; we can ignore the last icon
for (int i = 0; i < gapsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position += icon.getIconWidth();
}
position += localGaps[i];
min = (min <= position) ? min : position;
}
return (min < 0) ? -min : min;
}
private void paintIconRightToLeft(Component component, Graphics g, int x, int y) {
switch (this.alignment) {
case CENTER:
this.paintIconRightToLeftCenterAligned(component, g, x, y);
break;
case TOP:
this.paintIconRightToLeftTopAligned(component, g, x, y);
break;
case BOTTOM:
this.paintIconRightToLeftBottomAligned(component, g, x, y);
break;
default:
throw new IllegalStateException("illegal alignment: " + this.alignment);
}
}
private void paintIconRightToLeftCenterAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the height of the composite icon so we can center the nested icons in it
int totalHeight = this.getIconHeight();
// start the sliding position on the right
int position = x + this.getIconWidth() - this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position -= icon.getIconWidth();
icon.paintIcon(component, g, position, y + ((totalHeight - icon.getIconHeight()) >> 1));
}
if (i < gapsLength) {
position -= localGaps[i];
}
}
}
private void paintIconRightToLeftTopAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// start the sliding position on the right
int position = x + this.getIconWidth() - this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position -= icon.getIconWidth();
icon.paintIcon(component, g, position, y);
}
if (i < gapsLength) {
position -= localGaps[i];
}
}
}
private void paintIconRightToLeftBottomAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the bottom of the composite icon so we can position the nested icons there
int bottom = y + this.getIconHeight();
// start the sliding position on the right
int position = x + this.getIconWidth() - this.calculateHorizontalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position -= icon.getIconWidth();
icon.paintIcon(component, g, position, bottom - icon.getIconHeight());
}
if (i < gapsLength) {
position -= localGaps[i];
}
}
}
private void paintIconVertically(Component component, Graphics g, int x, int y) {
if (this.isLeftToRight(component)) {
this.paintIconTopToBottomLeadingEdgeOnLeft(component, g, x, y);
} else {
this.paintIconTopToBottomLeadingEdgeOnRight(component, g, x, y);
}
}
private void paintIconTopToBottomLeadingEdgeOnLeft(Component component, Graphics g, int x, int y) {
switch (this.alignment) {
case CENTER:
this.paintIconTopToBottomCenterAligned(component, g, x, y);
break;
case LEADING:
this.paintIconTopToBottomLeftAligned(component, g, x, y);
break;
case TRAILING:
this.paintIconTopToBottomRightAligned(component, g, x, y);
break;
default:
throw new IllegalStateException("illegal alignment: " + this.alignment);
}
}
private void paintIconTopToBottomCenterAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the width of the composite icon so we can center the nested icons in it
int totalWidth = this.getIconWidth();
// start the sliding position at the top
int position = y + this.calculateVerticalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, x + ((totalWidth - icon.getIconWidth()) >> 1), position);
position += icon.getIconHeight();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
// one of our two most performant options :-)
private void paintIconTopToBottomLeftAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// start the sliding position at the top
int position = y + this.calculateVerticalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, x, position);
position += icon.getIconHeight();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
private void paintIconTopToBottomRightAligned(Component component, Graphics g, int x, int y) {
Icon[] localIcons = this.icons;
int iconsLength = localIcons.length;
int[] localGaps = this.gaps;
int gapsLength = localGaps.length;
// cache the right edge of the composite icon so we can position the nested icons there
int right = x + this.getIconWidth();
// start the sliding position at the top
int position = y + this.calculateVerticalStartOffset();
for (int i = 0; i < iconsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
icon.paintIcon(component, g, right - icon.getIconWidth(), position);
position += icon.getIconHeight();
}
if (i < gapsLength) {
position += localGaps[i];
}
}
}
/**
* typically, the offset is zero; but it can be non-zero if
* there are any excessively negative gaps
*/
private int calculateVerticalStartOffset() {
Icon[] localIcons = this.icons;
int[] localGaps = this.gaps;
int position = 0;
int min = 0;
int gapsLength = localGaps.length;
// this loop MUST ascend; we can ignore the last icon
for (int i = 0; i < gapsLength; i++) {
Icon icon = localIcons[i];
if (icon != null) {
position += icon.getIconHeight();
}
position += localGaps[i];
min = (min <= position) ? min : position;
}
return (min < 0) ? -min : min;
}
private void paintIconTopToBottomLeadingEdgeOnRight(Component component, Graphics g, int x, int y) {
switch (this.alignment) {
case CENTER:
this.paintIconTopToBottomCenterAligned(component, g, x, y);
break;
case LEADING:
this.paintIconTopToBottomRightAligned(component, g, x, y);
break;
case TRAILING:
this.paintIconTopToBottomLeftAligned(component, g, x, y);
break;
default:
throw new IllegalStateException("illegal alignment: " + this.alignment);
}
}
// ********** Cloneable implementation **********
/**
* Clone the arrays so they are not shared.
* @see Object#clone()
*/
public Object clone() {
CompositeIcon clone;
try {
clone = (CompositeIcon) super.clone();
} catch (CloneNotSupportedException ex) {
throw new InternalError();
}
clone.icons = new Icon[this.icons.length];
System.arraycopy(this.icons, 0, clone.icons, 0, this.icons.length);
clone.gaps = new int[this.gaps.length];
System.arraycopy(this.gaps, 0, clone.gaps, 0, this.gaps.length);
clone.accessibleContext = null;
return clone;
}
// ********** Accessible implementation **********
/**
* @see javax.accessibility.Accessible#getAccessibleContext()
*/
public AccessibleContext getAccessibleContext() {
if (this.accessibleContext == null) {
this.accessibleContext = new AccessibleCompositeIcon();
}
return this.accessibleContext;
}
// ********** Object overrides **********
/**
* @see Object#toString()
*/
public String toString() {
return "CompositeIcon(" + this.icons.length + " icons)";
}
// ********** accessors **********
/**
* Return the icon at the specified position.
* @see icons
*/
public Icon getIcon(int index) {
return this.icons[index];
}
/**
* Set the icon at the specified position.
* @see icons
*/
public void setIcon(int index, Icon icon) {
this.icons[index] = icon;
}
/**
* Return the number of icons.
* @see icons
*/
public int iconCount() {
return this.icons.length;
}
/**
* Return the gap at the specified position.
* @see gaps
*/
public int getGap(int index) {
return this.gaps[index];
}
/**
* Set the gap at the specified position.
* @see gaps
*/
public void setGap(int index, int gap) {
this.gaps[index] = gap;
}
/**
* Return the number of gaps.
* @see gaps
*/
public int gapCount() {
return this.gaps.length;
}
private void addIcons(Icon[] extraIcons) {
Icon[] oldIcons = this.icons;
int oldLen = oldIcons.length;
int extraLen = extraIcons.length;
Icon[] newIcons = new Icon[oldLen + extraLen];
System.arraycopy(oldIcons, 0, newIcons, 0, oldLen);
System.arraycopy(extraIcons, 0, newIcons, oldLen, extraLen);
this.icons = newIcons;
}
private void addGaps(int[] extraGaps) {
int[] oldGaps = this.gaps;
int oldLen = oldGaps.length;
int extraLen = extraGaps.length;
int[] newGaps = new int[oldLen + extraLen];
System.arraycopy(oldGaps, 0, newGaps, 0, oldLen);
System.arraycopy(extraGaps, 0, newGaps, oldLen, extraLen);
this.gaps = newGaps;
}
/**
* Add the specified icons to the end of the list of icons
* with the specified gaps.
*/
public void addAll(Icon[] extraIcons, int[] extraGaps) {
if (extraIcons.length == 0) {
return;
}
if (this.icons.length == 0) {
if (extraGaps.length != extraIcons.length - 1) {
throw new IllegalArgumentException("there must be 1 fewer gaps than icons with the first addition to the composite");
}
} else {
if (extraGaps.length != extraIcons.length) {
throw new IllegalArgumentException("there must be same number of gaps as icons on subsequent additions to the composite");
}
}
this.addIcons(extraIcons);
this.addGaps(extraGaps);
}
/**
* Add the specified icons to the end of the list of icons
* with the specified fixed gap between them.
*/
public void addAll(Icon[] extraIcons, int gap) {
this.addAll(extraIcons, buildFixedGapsFor(extraIcons.length, gap));
}
/**
* Add the specified icons to the end of the list of icons
* with zero gaps between them.
*/
public void addAll(Icon[] extraIcons) {
this.addAll(extraIcons, 0);
}
/**
* Add the specified icons to the end of the list of icons
* with the specified fixed gap between them.
*/
public void addAll(List extraIcons, int gap) {
this.addAll((Icon[]) extraIcons.toArray(new Icon[extraIcons.size()]), gap);
}
/**
* Add the specified icons to the end of the list of icons
* with zero gaps between them.
*/
public void addAll(List extraIcons) {
this.addAll(extraIcons, 0);
}
/**
* Add the specified icon to the end of the list of icons
* with the specified gap.
*/
public void add(Icon icon, int gap) {
// ignore the gap if this is the first icon added
if (this.icons.length == 0) {
this.icons = new Icon[] {icon};
} else {
this.addAll(new Icon[] {icon}, new int[] {gap});
}
}
/**
* Add the specified icon to the end of the list of icons
* with a gap of zero.
*/
public void add(Icon icon) {
this.add(icon, 0);
}
/**
* Clear out all of the composite icon's icons and gaps.
*/
public void clear() {
this.icons = EMPTY_ICONS;
this.gaps = EMPTY_GAPS;
}
/**
* @see #orientation
*/
public int getOrientation() {
return this.orientation;
}
/**
* @see #orientation
*/
public void setOrientation(int orientation) {
if (this.orientation == orientation) {
return;
}
this.checkOrientation(orientation);
this.alignment = CENTER;
this.orientation = orientation;
}
private void checkOrientation(int orient) {
if ( ! CollectionTools.contains(VALID_ORIENTATION_VALUES, orient)) {
throw new IllegalArgumentException("invalid orientation: " + orient);
}
}
/**
* @see #alignment
*/
public int getAlignment() {
return this.alignment;
}
/**
* @see #orientation
*/
public void setAlignment(int alignment) {
this.checkAlignment(alignment);
this.alignment = alignment;
}
private void checkAlignment(int align) {
if (this.orientation == HORIZONTAL) {
if ( ! CollectionTools.contains(VALID_HORIZONTAL_ALIGNMENT_VALUES, align)) {
throw new IllegalArgumentException("invalid horizontal alignment: " + align);
}
} else { // VERTICAL
if ( ! CollectionTools.contains(VALID_VERTICAL_ALIGNMENT_VALUES, align)) {
throw new IllegalArgumentException("invalid vertical alignment: " + align);
}
}
}
/**
* @see #overrideLeftToRight
*/
public boolean isOverrideLeftToRight() {
return this.overrideLeftToRight;
}
/**
* @see #overrideLeftToRight
*/
public void setOverrideLeftToRight(boolean overrideLeftToRight) {
this.overrideLeftToRight = overrideLeftToRight;
}
/**
* If the composite icon's orientation is HORIZONTAL,
* return whether the component icons are painted from left-to-right.
* If the composite icon's orientation is VERTICAL,
* return whether the LEADING edge is on the left.
*/
private boolean isLeftToRight(Component component) {
return this.overrideLeftToRight || component.getComponentOrientation().isLeftToRight();
}
/**
* @see #description
*/
public String getDescription() {
return this.description;
}
/**
* @see #description
*/
public void setDescription(String description) {
this.description = description;
}
// ********** static methods **********
/**
* Return an array of gaps for a set of icons of
* the specified size, all of the same specified size.
*/
private static int[] buildFixedGapsFor(int iconsLength, int gap) {
if (iconsLength == 0) {
return EMPTY_GAPS;
}
return CollectionTools.fill(new int[iconsLength - 1], gap);
}
// ********** AccessibleContext implementation **********
/**
* This class implements accessibility support for the CompositeIcon.
* It provides an implementation of the Java Accessibility API
* appropriate to array icon user-interface elements.
*/
protected class AccessibleCompositeIcon
extends AccessibleContext
implements AccessibleIcon, Serializable
{
/**
* @see javax.accessibility.AccessibleContext#getAccessibleRole()
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.ICON;
}
/**
* @see javax.accessibility.AccessibleContext#getAccessibleStateSet()
*/
public AccessibleStateSet getAccessibleStateSet() {
return null;
}
/**
* @see javax.accessibility.AccessibleContext#getAccessibleParent()
*/
public Accessible getAccessibleParent() {
return null;
}
/**
* @see javax.accessibility.AccessibleContext#getAccessibleIndexInParent()
*/
public int getAccessibleIndexInParent() {
return -1;
}
/**
* @see javax.accessibility.AccessibleContext#getAccessibleChildrenCount()
*/
public int getAccessibleChildrenCount() {
Icon[] localIcons = CompositeIcon.this.icons;
int len = localIcons.length;
int count = 0;
for (int i = 0; i < len; i++) {
if (localIcons[i] instanceof Accessible) {
count++;
}
}
return count;
}
/**
* @see javax.accessibility.AccessibleContext#getAccessibleChild(int)
*/
public Accessible getAccessibleChild(int index) {
Icon[] localIcons = CompositeIcon.this.icons;
int len = localIcons.length;
int count = 0;
for (int i = 0; i < len; i++) {
Icon icon = localIcons[i];
if (icon instanceof Accessible) {
if (count == index) {
return (Accessible) icon;
}
count++;
}
}
return null;
}
/**
* @see javax.accessibility.AccessibleContext#getLocale()
*/
public Locale getLocale() {
return null;
}
/**
* @see javax.accessibility.AccessibleIcon#getAccessibleIconDescription()
*/
public String getAccessibleIconDescription() {
return CompositeIcon.this.getDescription();
}
/**
* @see javax.accessibility.AccessibleIcon#setAccessibleIconDescription(java.lang.String)
*/
public void setAccessibleIconDescription(String description) {
CompositeIcon.this.setDescription(description);
}
/**
* @see javax.accessibility.AccessibleIcon#getAccessibleIconHeight()
*/
public int getAccessibleIconHeight() {
return CompositeIcon.this.getIconHeight();
}
/**
* @see javax.accessibility.AccessibleIcon#getAccessibleIconWidth()
*/
public int getAccessibleIconWidth() {
return CompositeIcon.this.getIconWidth();
}
}
}