/*
Copyright (c) 2003-2009 ITerative Consulting Pty Ltd. 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 This jcTOOL Helper Class software, whether in binary or source form may not be used within,
or to derive, any other product without the specific prior written permission of the copyright holder
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "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 DisplayProject;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JToggleButton;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import DisplayProject.actions.ActionMgr;
import DisplayProject.actions.PendingAction;
import DisplayProject.events.ClientEventManager;
import Framework.Array_Of_ListElement;
import Framework.CloneHelper;
import Framework.ErrorMgr;
import Framework.ImageData;
import Framework.ListElement;
import Framework.TextData;
import Framework.UsageException;
/**
* The PaletteList class defines a palette list, which displays a group of options as uniformly-sized, clickable cells organized into a vertical or horizontal bar. A user can select no more than one option from the palette list at any time.
*/
@SuppressWarnings("serial")
public class PaletteList extends JComponent implements ListField{
protected ArrayList<JToggleButton> buttons = new ArrayList<JToggleButton>();
protected Array_Of_ListElement<ListElement> listElements = new Array_Of_ListElement<ListElement>();
protected int orientation = Constants.FO_VERTICAL;
protected int wrapSize = 1;
private int selectedIndex = -1;
protected ListModel dataModel;
private ListSelectionListener selectionListener;
private ListSelectionModel selectionModel;
public PaletteList() {
GridLayout aLayout = new GridLayout(0,1);
this.setLayout(aLayout);
}
public void setElementList(Array_Of_ListElement<ListElement> pElements) {
final Array_Of_ListElement<ListElement> elements = CloneHelper.clone(pElements, false);
ActionMgr.addAction(new PendingAction(null){
@Override
public void performAction() {
synchronized (PaletteList.this) {
PaletteList.this.removeAll();
PaletteList.this.listElements.clear();
Dimension imageSize = PaletteList.this.getImageSize(elements);
for (Iterator<ListElement> it = elements.iterator(); it.hasNext();) {
ListElement le = it.next();
if (le.getImageValue() != null && !le.getImageValue().isNull()) {
ImageData id = le.getImageValue();
ImageIcon thisImage = new ImageIcon(id.getValue());
JToggleButton thisButton = new JToggleButton(PaletteList.this.makeTransparentIcon(thisImage));
thisButton.setPreferredSize(imageSize);
thisButton.setMinimumSize(imageSize);
thisButton.setMaximumSize(imageSize);
thisButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
PaletteList.this.actionChange(arg0);
}
});
buttons.add(thisButton);
PaletteList.this.add(thisButton);
PaletteList.this.listElements.add(le);
}
}
}
}
});
}
public Array_Of_ListElement<ListElement> getElementList(){
return this.listElements;
}
public int getOrientation() {
return this.orientation;
}
public void setOrientation(int pOrientation) {
GridLayout aLayout = (GridLayout)this.getLayout();
switch (pOrientation) {
case Constants.FO_HORIZONTAL:
aLayout.setRows(this.wrapSize);
aLayout.setColumns(0);
break;
case Constants.FO_VERTICAL:
aLayout.setRows(0);
aLayout.setColumns(this.wrapSize);
break;
default:
aLayout.setRows(0);
aLayout.setColumns(this.wrapSize);
break;
}
this.orientation = pOrientation;
}
public void setWrapSize(int pWrapSize) {
if (pWrapSize > 0) {
this.wrapSize = pWrapSize;
GridLayout aLayout = (GridLayout)this.getLayout();
if (this.orientation == Constants.FO_HORIZONTAL) {
aLayout.setRows(this.wrapSize);
aLayout.setColumns(0);
}
else {
aLayout.setRows(0);
aLayout.setColumns(this.wrapSize);
}
}
else {
UsageException errorVar = new UsageException("pWrapSize must be greater than 0");
ErrorMgr.addError(errorVar);
throw errorVar;
}
}
public int getSelectedIndex(){
return this.selectedIndex;
}
public void setSelectedIndex(int pIndex) {
JToggleButton thisButton = null;
if (pIndex >= 0 && pIndex < this.buttons.size()) {
thisButton = (JToggleButton)this.buttons.get(pIndex);
}
if (pIndex != this.selectedIndex) {
if (this.selectedIndex >= 0) {
JToggleButton b = (JToggleButton)this.buttons.get(this.selectedIndex);
((JToggleButton.ToggleButtonModel)(b.getModel())).setSelected(false);
}
if (thisButton != null) {
this.selectedIndex = pIndex;
JToggleButton.ToggleButtonModel thisModel = (JToggleButton.ToggleButtonModel)thisButton.getModel();
thisModel.setSelected(true);
}
else {
this.selectedIndex = -1;
}
}
this.selectionModel.setLeadSelectionIndex(this.selectedIndex);
this.fireSelectionValueChanged(this.selectedIndex, this.selectedIndex, false);
ClientEventManager.postEvent(this, "AfterValueChange");
}
protected Dimension getImageSize(ImageIcon[] pList) {
int width = 0;
int height = 0;
for (int i = 0; i < pList.length; i++) {
int thisWidth = pList[i].getIconWidth();
if (thisWidth > width) {
width = thisWidth;
}
int thisHeight = pList[i].getIconHeight();
if (thisHeight > height) {
height = thisHeight;
}
}
return new Dimension(width+4, height+4);
}
protected Dimension getImageSize(Array_Of_ListElement<ListElement> pElements) {
int width = 0;
int height = 0;
for (Iterator<ListElement> it = pElements.iterator(); it.hasNext(); ) {
ListElement thisElement = it.next();
ImageData thisImage = thisElement.getImageValue();
if (thisImage != null) {
Image anImage = thisImage.getValue();
// Force this image to be fully realized
ImageIcon i = new ImageIcon(anImage);
int thisWidth = i.getIconWidth();
if (thisWidth > width) {
width = thisWidth;
}
int thisHeight = i.getIconHeight();
if (thisHeight > height) {
height = thisHeight;
}
}
}
return new Dimension(width+4, height+4);
}
protected ImageIcon makeTransparentIcon(ImageIcon pIcon) {
//PM:25/4/08 simplified this code by calling a common method
// Create a buffered image with a format that's compatible with the screen
BufferedImage bimage = new BufferedImage(pIcon.getIconWidth(), pIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
// Paint the image onto the buffered image
pIcon.paintIcon(this, bimage.createGraphics(),0,0);
UIutils.transparentImage(bimage);
return new ImageIcon(bimage);
}
//PM:25/4/08 no longer neaded
// // This method returns true if the specified image has transparent pixels
// public boolean hasAlpha(Image image) {
// // If buffered image, the color model is readily available
// if (image instanceof BufferedImage) {
// BufferedImage bimage = (BufferedImage)image;
// return bimage.getColorModel().hasAlpha();
// }
//
// // Use a pixel grabber to retrieve the image's color model;
// // grabbing a single pixel is usually sufficient
// PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
// try {
// pg.grabPixels();
// } catch (InterruptedException e) {
// CancelException errorVar = new CancelException(e);
// ErrorMgr.addError(errorVar);
// throw errorVar;
// }
//
// // Get the image's color model
// ColorModel cm = pg.getColorModel();
// if (cm == null)
// return false;
// return cm.hasAlpha();
// }
/**
* CraigM:22/04/2008.
*
* @see ArrayList#indexOf(Object)
* @param pBtn
* @return
*/
public int getIndexValue(JToggleButton pBtn) {
return this.buttons.indexOf(pBtn);
}
protected void actionChange(ActionEvent pEvent) {
JToggleButton thisButton = (JToggleButton)pEvent.getSource();
int anIndex = this.buttons.indexOf(thisButton);
this.setSelectedIndex(anIndex);
}
public void setSelectionModel(ListSelectionModel selectionModel) {
if (selectionModel == null) {
UsageException errorVar = new UsageException("selectionModel must be non null");
ErrorMgr.addError(errorVar);
throw errorVar;
}
/* Remove the forwarding ListSelectionListener from the old
* selectionModel, and add it to the new one, if necessary.
*/
if (selectionListener != null) {
this.selectionModel.removeListSelectionListener(selectionListener);
selectionModel.addListSelectionListener(selectionListener);
}
ListSelectionModel oldValue = this.selectionModel;
this.selectionModel = selectionModel;
firePropertyChange("selectionModel", oldValue, selectionModel);
}
protected void fireSelectionValueChanged(int firstIndex, int lastIndex,
boolean isAdjusting)
{
Object[] listeners = listenerList.getListenerList();
ListSelectionEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ListSelectionListener.class) {
if (e == null) {
e = new ListSelectionEvent(this, firstIndex, lastIndex,
isAdjusting);
}
((ListSelectionListener)listeners[i+1]).valueChanged(e);
}
}
}
public int getIntegerValue() {
return this.listElements.get(getSelectedIndex()).getIntegerValue();
}
public Object getObjectValue() {
return this.listElements.get(getSelectedIndex()).getObjectValue();
}
public TextData getTextValue() {
return this.listElements.get(getSelectedIndex()).getTextValue();
}
public void setIntegerValue(int value) {
for (ListElement le : this.listElements) {
if (le.getIntegerValue() == value){
this.setSelectedIndex(this.listElements.indexOf(le));
break;
}
}
}
public void setObjectValue(Object value) {
if (value == null){
this.setSelectedIndex(-1);
return;
}
for (ListElement le : this.listElements) {
if (le.getObjectValue() == null)
continue;
if (le.getObjectValue().equals(value)){
this.setSelectedIndex(this.listElements.indexOf(le));
break;
}
}
}
public void setTextValue(TextData value) {
if (value == null){
this.setSelectedIndex(-1);
return;
}
for (ListElement le : this.listElements) {
if (le.getTextValue() == null)
continue;
if (le.getTextValue().toString().equals(value.toLower())){
this.setSelectedIndex(this.listElements.indexOf(le));
break;
}
}
}
/* (non-Javadoc)
* @see ListField#setElementSelected(int, boolean)
* @author AD:26/5/2008
*/
public void setElementSelected(int index, boolean isSelected) {
if (isSelected) {
this.setSelectedIndex(index);
} else {
// Set no item to be selected
this.setSelectedIndex(-1);
}
}
}