/*
* Copyright (C) 2005 David Orme <djo@coconut-palm-software.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Orme - Initial API and implementation
* The Pampered Chef - Expanded to handle sorting
*/
package org.eclipse.swt.nebula.widgets.compositetable;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
/**
* Class AbstractSortableHeader. A Header class making it easier to implement a
* sorted table where clicking on a header column sets or changes the sort
* order.
*
* @author djo
*/
public abstract class AbstractSortableHeader extends Composite {
protected List labels;
private String[] labelStrings;
private MouseAdapter sortMouseAdapter;
private Boolean sortDescending = null; // choices: null (no sort); true; false
private int lastSortColumn = -1;
protected Image sortUpIndicator = new Image(Display.getDefault(), getUpImageData());
protected Image sortDownIndicator = new Image(Display.getDefault(), getDownImageData());
private Image sortIndicator = null;
final int width = 8;
final int height = 4;
private ImageData getEmptyImageData() {
final RGB whiteRGB = new RGB(255, 255, 255); // The transparancy color
final RGB blackRGB = new RGB(0, 0, 0);
PaletteData palette = new PaletteData(new RGB[] { whiteRGB, blackRGB });
ImageData imageData = new ImageData(width, height, 1, palette);
int whitePixel = imageData.palette.getPixel(whiteRGB);
imageData.transparentPixel = whitePixel;
return imageData;
}
private ImageData getUpImageData() {
ImageData imageData = getEmptyImageData();
int numTransparentPixels = 0;
for (int row = height - 1; row >= 0; --row) {
for (int col = numTransparentPixels; col < width / 2; ++col) {
imageData.setPixel(col, row, 1);
imageData.setPixel(width - col - 1, row, 1);
}
++numTransparentPixels;
}
return imageData;
}
private ImageData getDownImageData() {
ImageData imageData = getEmptyImageData();
int numTransparentPixels = 0;
for (int row = 0; row < height; ++row) {
for (int col = numTransparentPixels; col < width / 2; ++col) {
imageData.setPixel(col, row, 1);
imageData.setPixel(width - col - 1, row, 1);
}
++numTransparentPixels;
}
return imageData;
}
/**
*
* @param parent
* @param style
*/
public AbstractSortableHeader(Composite parent, int style) {
super(parent, style);
makeMouseAdapter();
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent arg0) {
sortUpIndicator.dispose();
sortDownIndicator.dispose();
}
});
}
private boolean toggleSortDirection() {
if (sortDescending == null) {
sortDescending = Boolean.TRUE;
sortIndicator = sortDownIndicator;
return sortDescending.booleanValue();
}
sortDescending = new Boolean(!sortDescending.booleanValue());
if (sortDescending.booleanValue()) {
sortIndicator = sortDownIndicator;
} else {
sortIndicator = sortUpIndicator;
}
return sortDescending.booleanValue();
}
private void makeMouseAdapter() {
this.sortMouseAdapter = new MouseAdapter() {
public void mouseDown(MouseEvent e) {
CLabel label = (CLabel) e.widget;
int c = labels.indexOf(label);
if (c != lastSortColumn) {
sortDescending = null;
sortIndicator = null;
}
lastSortColumn = c;
sortOnColumn(c, toggleSortDirection());
for (int i = 0; i < labels.size(); i++) {
CLabel labelToSet = (CLabel) labels.get(i);
if (i != c) {
labelToSet.setImage(null);
} else {
labelToSet.setImage(sortIndicator);
}
}
}
};
}
/**
* Clients must override this method to reset the current sort column.
*
* @param column
* The column on which to sort
* @param sortDescending
* true if the sort should be in descending order; false for
* ascending order
*/
protected abstract void sortOnColumn(int column, boolean sortDescending);
/**
* Clients must call this method (normally in the constructor) to set the
* column names.
*
* @param columnText String[] The text to display in each column
*/
public void setColumnText(String[] columnText) {
this.labelStrings = columnText;
initialize();
}
private void initialize() {
this.labels = new ArrayList();
String[] fields = labelStrings;
for (int i = 0; i < fields.length; i++) {
CLabel label = new CLabel(this, SWT.NONE);
if (label.isDisposed()) return;
this.labels.add(label);
label.setText(fields[i]);
initializeLabel(label);
}
}
protected void initializeLabel(CLabel label) {
label.addMouseListener(this.sortMouseAdapter);
}
}