package com.explodingpixels.macwidgets;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Icon;
import com.explodingpixels.widgets.IconProvider;
import com.explodingpixels.widgets.TextProvider;
/**
* An item in a {@link com.explodingpixels.macwidgets.SourceList} which is contained within a {@link SourceListCategory}.
*/
public class SourceListItem implements TextProvider, IconProvider, SourceListBadgeContentProvider {
public static final String TEXT = "text";
public static final String ICON = "icon";
public static final String COUNTER_VALUE = "counter";
private List<SourceListItem> fChildItems = new ArrayList<SourceListItem>();
private String fText;
private Icon fIcon;
private int fCounterValue;
private PropertyChangeSupport fSupport = new PropertyChangeSupport(this);
/**
* Creates a {@code SourceListItem} with the given text.
*
* @param text the item text. Cannot be null.
* @throws IllegalArgumentException if the text is null.
*/
public SourceListItem(String text) {
this(text, null);
}
/**
* Creates a {@code SourceListItem} with the given text and icon.
*
* @param text the item text. Cannot be null.
* @param icon the item icon. Can be null.
* @throws IllegalArgumentException if the text is null.
*/
public SourceListItem(String text, Icon icon) {
checkText(text);
fText = text;
fIcon = icon;
}
/**
* Gets the text to use for this item.
*
* @return the text to use for this item.
*/
public String getText() {
return fText;
}
/**
* Sets the text to use for this item.
*
* @param text the text to use for this item. Cannot be null.
* @throws IllegalArgumentException if the text is null.
*/
public void setText(String text) {
checkText(text);
String oldText = fText;
fText = text;
fSupport.firePropertyChange(TEXT, oldText, fText);
}
/**
* Gets the icon to use for this item.
*
* @return the icon to use for this item.
*/
public Icon getIcon() {
return fIcon;
}
/**
* Sets the icon to use for this item.
*
* @param icon the icon to use for this item. Can be null.
*/
public void setIcon(Icon icon) {
Icon oldIcon = fIcon;
fIcon = icon;
fSupport.firePropertyChange(ICON, oldIcon, fIcon);
}
boolean hasCounterValue() {
return getCounterValue() > 0;
}
/**
* Gets the counter value to use for this item. The counter value will be displayed to the right
* of the item.
*
* @return the counter value to use for this item.
*/
public int getCounterValue() {
return fCounterValue;
}
/**
* {@inheritDoc}
*/
public String getBadgeValue() {
return "" + fCounterValue;
}
/**
* Sets the counter value to use for this item. The counter value will be displayed to the right
* of the item.
*
* @param counterValue the counter value to use for this item. Must be >= 0.
* @throws IllegalArgumentException if the counter value is not >= 0.
*/
public void setCounterValue(int counterValue) {
checkCount(counterValue);
int oldCounterValue = fCounterValue;
fCounterValue = counterValue;
fSupport.firePropertyChange(COUNTER_VALUE, oldCounterValue, fCounterValue);
}
/**
* Returns {@code true} if the given {@link com.explodingpixels.macwidgets.SourceListItem} is contained by this item, to
* include being a sub-element of another child {@code SourceListItem}.
*
* @param item the {@code SourceListItem} to determine whether or not is contained by this
* item.
* @return {@code true} if the given {@code SourceListItem} is contained within this item
* or within on of this items child {@code SourceListItem}s.
*/
public boolean containsItem(SourceListItem item) {
boolean contains = fChildItems.contains(item);
if (!contains) {
for (SourceListItem childItem : fChildItems) {
contains = childItem.containsItem(item);
if (contains) {
break;
}
}
}
return contains;
}
/**
* Returns a {@link String} representation of this {@code SourceListItem}.
*
* @return a {@link String} representation of this {@code SourceListItem}.
*/
@Override
public String toString() {
return getText();
}
/**
* Gets a list of this {@code SourceListItem}'s child {@code SourceListItem}s.
*
* @return a list of this {@code SourceListItem}'s child {@code SourceListItem}s.
*/
public List<SourceListItem> getChildItems() {
return Collections.unmodifiableList(fChildItems);
}
int indexOfItem(SourceListItem item) {
return fChildItems.indexOf(item);
}
int getChildCount() {
return fChildItems.size();
}
void addItem(SourceListItem childItem) {
fChildItems.add(childItem);
}
void addItem(int index, SourceListItem childItem) {
fChildItems.add(index, childItem);
}
void removeItem(SourceListItem childItem) {
fChildItems.remove(childItem);
}
SourceListItem removeItem(int index) {
return fChildItems.remove(index);
}
// Property change support. ///////////////////////////////////////////////////////////////////
/**
* Adds a {@link java.beans.PropertyChangeListener} on this {@code SourceListItem}.
*
* @param listener the listener to add.
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
fSupport.addPropertyChangeListener(listener);
}
/**
* Removes a {@link java.beans.PropertyChangeListener} from this {@code SourceListItem}.
*
* @param listener the listener to remove.
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
fSupport.removePropertyChangeListener(listener);
}
// Utility methods. ///////////////////////////////////////////////////////////////////////////
private void checkCount(int count) {
if (count < 0) {
throw new IllegalArgumentException("Count must be zero or greater.");
}
}
private void checkText(String text) {
if (text == null) {
throw new IllegalArgumentException("Text cannot be null.");
}
}
}