/*
* Created on 19.02.2005
*/
package gui;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
/**
* Klasse, die von JTable abgeleitet ist und um eine Sortier-Funktion für eine
* angeklickte Spalte erweitert wurde.
*
* @author Thomas Quadflieg
*/
public class SortierbaresJTable extends JTable implements MouseListener
{
private NichtEditierbaresDefaultTableModel tableModel;
private int sortierteSpalteIst; /* Wird im Konstruktor zunächst auf -1 gesetzt. Gibt nach der ersten Sortierung an,
nach welcher Spalte sortiert aktuell sortiert ist.*/
private boolean abwaertsSortieren; /* Wird im Konstruktor zunächst auf true gesetzt. Gibt an, ob abwaerts (true)
oder aufwärts (false) sortiert werden soll. */
/**
* Erzeugt ein Objekt von SortierbaresJTable
*
* @param spaltenNamen Vector, der die Spaltenüberschriften (Strings)
* enthält. Legt gleichzeitig fest, wie viele Spalten das JTable hat.
* @param singleSelection true-->SINGLE_SELECTION
* false-->MULTIPLE_INTERVAL_SELECTION
*/
public SortierbaresJTable(Vector spaltenNamen, boolean singleSelection)
{
getTableHeader().addMouseListener(this);
tableModel = new NichtEditierbaresDefaultTableModel(spaltenNamen);
setModel(tableModel);
setSingleSelection(singleSelection);
sortierteSpalteIst = -1;
getTableHeader().setReorderingAllowed(false);
abwaertsSortieren = true;
}
/**
* Methode zum setzen des SelectionMode (vereinfachte Form der Methode
* setSelectionMode(int arg0))
*
* @param singleSelection true-->SINGLE_SELECTION
* false-->MULTIPLE_INTERVAL_SELECTION
*/
public void setSingleSelection(boolean singleSelection)
{
if(singleSelection)
{
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
else
{
setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
}
}
/**
* Wenn die MouseTaste auf dem TableHeader gedrückt wurde wird diese Methode
* für die Sortierung aufgerufen
*
* @param arg0 ausloesender MouseEvent
*/
public void mousePressed(MouseEvent arg0)
{
// Spalte nach der Sortiert werden soll
int sortierteSpalteSoll = columnAtPoint(arg0.getPoint());
/* Wenn die zu sortierendeSpalte schon abwartssortiert ist wird abwaertsSortieren=false,
* andernfalls true.
*/
if((sortierteSpalteSoll == sortierteSpalteIst)
&& (abwaertsSortieren == true))
{
abwaertsSortieren = false;
}
else
{
abwaertsSortieren = true;
}
// Anzahl der Zeilen bzw. Spalten
int anzahlZeilen = this.getRowCount();
int anzahlSpalten = this.getColumnCount();
/* --- Überprüfung auf String ---
* In einem Try-Catch-Zweig wird versucht in einer Schleife nacheinander
* jeden Zellen-Wert der selektierten Spalte von String zu Double umzuwandeln.
* Wird hierbei eine Exception geschmissen ist klar, dass es sich bei den Werten
* der Spalte um Strings handelt (beim ersten Durchlauf wird danach noch zwischen Datum und String unterschieden)
* Andernfalls wird nach dem Zahlen-Ordnung soritert.
* Diese Überprüfung ist notwendig, da bei einer Sortierung nach String eine Zahlenreihe
* folgendermaßen sortiert würde: 12,132,157,18,2,23,usw.
*/
String zellenWertZumTest;
boolean isString = false;
boolean isDatum = true;
try
{
for(int i = 0; i < anzahlZeilen; i++)
{
try
{
zellenWertZumTest = getValueAt(i, sortierteSpalteSoll).toString();
Double.parseDouble(zellenWertZumTest);
// Wenn der erste Wert eine Zahl ist, wird die Datumsprüfung nicht mehr fortgesetzt.
if(isDatum)
{
isDatum = false;
}
}
catch(NullPointerException e)
{
}
}
}
catch(NumberFormatException e)
{
isString = true;
// Wenn der erste Zeilenwert der zu sortierenden Spalte keine Zahl ist wird geprüft, ob es sich um ein Datum handelt
if(isDatum)
{
// Die isString-Variable wird zunächst wieder auf false gesetzt.
// Sollte im folgenden Try-Catch-Zweig festgestellt werden, dass
// in der zu sortierenden Spalte kein Datumsformat vorliegt wird sie wieder auf true gesetzt.
isString = false;
try
{
// Die Schleife prüft jede Zelle der Spalte auf das Datumsformat solange bis eine Zelle
// kein Datumsformat ist oder alle Zellen erfolgreich geprüft wurden
for(int i = 0; i < anzahlZeilen; i++)
{
try
{
// Der Zellenwert wird in die Variable zellenWertZumTest (String) geschrieben.
zellenWertZumTest = getValueAt(i, sortierteSpalteSoll).toString();
// Wenn der 3. und 6. Charakter ein Punkt ist (Trennzeichen bei DD.MM.YYYY) werden die
// restlichen Stellen auf int-Werte geprüft.
if((zellenWertZumTest.charAt(2) == '.')
&& (zellenWertZumTest.charAt(5) == '.'))
{
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(0)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(1)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(3)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(4)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(6)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(7)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(8)));
Integer.parseInt(Character.toString(zellenWertZumTest.charAt(9)));
}
else
{
isDatum = false;
isString = true;
break;
}
}
catch(NullPointerException e2)
{
}
catch(StringIndexOutOfBoundsException e3)
{
}
}
}
catch(NumberFormatException e2)
{
//Wenn an der Stelle 3 und 6 ein Punkt ist, im restlichen Teil jedoch nicht ausnahmslos zahlen
// wird diese Exception geschmiessen und die Schleife abgebrochen, da klar ist, dass es sich
// bei dem Format der Spalte um Strings handelt.
isDatum = false;
isString = true;
}
}
}
/* Diese Verzweigung ist notwendig für die unterschiedlichen Sortier-Arten von
Strings, Datum, Zahlen */
if(isString)
{
String[][] sortierSpalte = new String[2][anzahlZeilen];
/* --- Anlegen eines zweidimensionalen Arrays mit Spalteninhalt+Index ---
* In dieser Zählschleife wird ein Array
* mit den Werten der Spalte und ihrer
* jeweiligen Position gefüllt.
* Bsp:
* 3 Zeilen mit Inhalt: Korn, Apfel, Bier.
* [0][0]-->0
* [1][0]-->Korn
* [0][1]-->1
* [1][1]-->Apfel
* [0][2]-->2
* [1][2]-->Bier
*/
for(int i = 0; i < anzahlZeilen; i++)
{
sortierSpalte[0][i] = Integer.toString(i);
try
{
sortierSpalte[1][i] = getValueAt(i, sortierteSpalteSoll).toString();
}
catch(NullPointerException e)
{
sortierSpalte[1][i] = " ";
}
}
/* --- SelectionSort ---
* Es wird z.Zt. nur Absteigend sortiert.
* Bsp (nach abgeschlossener Sortierung):
* [0][0]-->1
* [1][0]-->Apfel
* [0][1]-->2
* [1][1]-->Bier
* [0][2]-->0
* [1][2]-->Korn
*/
for(int i = 0; i < (anzahlZeilen - 1); i++)
{
int min = i;
for(int j = i; j < anzahlZeilen; j++)
{
// Verzweigung Abwärts- (if) bzw. Aufwärts-Sortierung (else)
if(abwaertsSortieren)
{
if(sortierSpalte[1][j].compareToIgnoreCase(sortierSpalte[1][min]) < 0)
{
min = j;
}
}
else
{
if(sortierSpalte[1][j].compareToIgnoreCase(sortierSpalte[1][min]) > 0)
{
min = j;
}
}
}
String tmp = sortierSpalte[0][i];
sortierSpalte[0][i] = sortierSpalte[0][min];
sortierSpalte[0][min] = tmp;
String tmp2 = sortierSpalte[1][i];
sortierSpalte[1][i] = sortierSpalte[1][min];
sortierSpalte[1][min] = tmp2;
}
/*
* Das Array sortierSpalte ist nun sortiert. Für die nächsten Schritte wird
* der Inhalt der Spalte nicht mehr benötigt, lediglich der Index ist noch von Bedeutung.
*/
/*
* In diesem Schritt wird mittels eines Arrays in einer Schleife ein Vector mit dem Inhalt
* jeder Zeile gefüllt.
*/
Vector[] vectorZeile = new Vector[anzahlZeilen];
for(int i = 0; i < anzahlZeilen; i++)
{
vectorZeile[i] = new Vector();
for(int j = 0; j < anzahlSpalten; j++)
{
vectorZeile[i].add(this.getValueAt(i, j));
}
}
/*
* Nachdem alle Zeilen nun in dem Vector-Array gespeichert sind wird zeilenweise der
* Vectorinhalt dem TableModel hinzugefügt. Im gleichen Schritt wird die oberste
* Zeile gelöscht. Nach Komplett-Durchlauf dieser Schleife sind alle vorhandenen,
* unsortierten Zeilen entfernt worden und durch die sortierten ersetzt worden. *
*/
int zeile;
for(int i = 0; i < anzahlZeilen; i++)
{
zeile = Integer.parseInt(sortierSpalte[0][i]);
tableModel.addRow(vectorZeile[zeile]);
tableModel.removeRow(0);
}
}
// Sortierung nach Datum
else if(isDatum)
{
int[][] sortierSpalte = new int[2][anzahlZeilen];
// In dieser Schleife wird zunächst der ZellenWert ausgelesen.
// Danach wird die jeweilige Array-Position mit dem Datum gefüllt:
// Aus DD.MM.YYYY wird ein Int-Wert YYYYMMDD
// (Bsp: 17.02.1983 --> 19830217)
// Dieser Wert kann später genau so sortiert werden, wie ein
// normaler Zahlenwert.
for(int i = 0; i < anzahlZeilen; i++)
{
sortierSpalte[0][i] = i;
try
{
String zellenWert = getValueAt(i, sortierteSpalteSoll).toString();
sortierSpalte[1][i] = Integer.parseInt(Character.toString(
zellenWert.charAt(6))) * 10000000;
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(7))) * 1000000);
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(8))) * 100000);
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(9))) * 10000);
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(3))) * 1000);
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(4))) * 100);
sortierSpalte[1][i] += (Integer.parseInt(Character.toString(
zellenWert.charAt(0))) * 10);
sortierSpalte[1][i] += Integer.parseInt(Character.toString(
zellenWert.charAt(1)));
}
catch(NullPointerException e)
{
sortierSpalte[1][i] = -99999999;
}
catch(StringIndexOutOfBoundsException e2)
{
sortierSpalte[1][i] = -99999999;
}
}
/* --- SelectionSort ---
* Es wird z.Zt. nur Absteigend sortiert.
* Bsp (nach abgeschlossener Sortierung):
* [0][0]-->1
* [1][0]-->2
* [0][1]-->0
* [1][1]-->5
* [0][2]-->2
* [1][2]-->12
*/
for(int i = 0; i < (anzahlZeilen - 1); i++)
{
int min = i;
for(int j = i; j < anzahlZeilen; j++)
{
// Verzweigung Abwärts- (if) bzw. Aufwärts-Sortierung (else)
if(abwaertsSortieren)
{
if(sortierSpalte[1][j] < (sortierSpalte[1][min]))
{
min = j;
}
}
else
{
if(sortierSpalte[1][j] > (sortierSpalte[1][min]))
{
min = j;
}
}
}
int tmp = sortierSpalte[0][i];
sortierSpalte[0][i] = sortierSpalte[0][min];
sortierSpalte[0][min] = tmp;
int tmp2 = sortierSpalte[1][i];
sortierSpalte[1][i] = sortierSpalte[1][min];
sortierSpalte[1][min] = tmp2;
}
/*
* Das Array sortierSpalte ist nun sortiert. Für die nächsten Schritte wird
* der Inhalt der Spalte nicht mehr benötigt, lediglich der Index ist noch von Bedeutung.
*/
/*
* In diesem Schritt wird mittels eines Arrays in einer Schleife ein Vector mit dem Inhalt
* jeder Zeile gefüllt.
*/
Vector[] vectorZeile = new Vector[anzahlZeilen];
for(int i = 0; i < anzahlZeilen; i++)
{
vectorZeile[i] = new Vector();
for(int j = 0; j < anzahlSpalten; j++)
{
vectorZeile[i].add(this.getValueAt(i, j));
}
}
int zeile;
/*
* Nachdem alle Zeilen nun in dem Vector-Array gespeichert sind wird zeilenweise der
* Vectorinhalt dem TableModel hinzugefügt. Im gleichen Schritt wird die oberste
* Zeile gelöscht. Nach Komplett-Durchlauf dieser Schleife sind alle vorhandenen,
* unsortierten Zeilen entfernt worden und durch die sortierten ersetzt worden. *
*/
for(int i = 0; i < anzahlZeilen; i++)
{
zeile = (int) sortierSpalte[0][i];
tableModel.addRow(vectorZeile[zeile]);
tableModel.removeRow(0);
}
}
// Der Else-Zweig wird aufgerufen, wenn es sich bei dem Spalten-Inhalt ausschließlich um
// Zahlen handelt.
else
{
double[][] sortierSpalte = new double[2][anzahlZeilen];
/* --- Anlegen eines zweidimensionalen Arrays mit Spalteninhalt+Index ---
* In dieser Zählschleife wird ein Array
* mit den Werten der Spalte und ihrer
* jeweiligen Position gefüllt.
* Bsp:
* 3 Zeilen mit Inhalt: 5.8, 2, 12.
* [0][0]-->0
* [1][0]-->5
* [0][1]-->1
* [1][1]-->2
* [0][2]-->2
* [1][2]-->12
* */
for(int i = 0; i < anzahlZeilen; i++)
{
sortierSpalte[0][i] = i;
try
{
sortierSpalte[1][i] = Double.parseDouble(getValueAt(i,
sortierteSpalteSoll).toString());
}
catch(NullPointerException e)
{
sortierSpalte[1][i] = -999999999;
}
}
/* --- SelectionSort ---
* Es wird z.Zt. nur Absteigend sortiert.
* Bsp (nach abgeschlossener Sortierung):
* [0][0]-->1
* [1][0]-->2
* [0][1]-->0
* [1][1]-->5.8
* [0][2]-->2
* [1][2]-->12
*/
for(int i = 0; i < (anzahlZeilen - 1); i++)
{
int min = i;
for(int j = i; j < anzahlZeilen; j++)
{
// Verzweigung Abwärts- (if) bzw. Aufwärts-Sortierung (else)
if(abwaertsSortieren)
{
if(sortierSpalte[1][j] < (sortierSpalte[1][min]))
{
min = j;
}
}
else
{
if(sortierSpalte[1][j] > (sortierSpalte[1][min]))
{
min = j;
}
}
}
double tmp = sortierSpalte[0][i];
sortierSpalte[0][i] = sortierSpalte[0][min];
sortierSpalte[0][min] = tmp;
double tmp2 = sortierSpalte[1][i];
sortierSpalte[1][i] = sortierSpalte[1][min];
sortierSpalte[1][min] = tmp2;
}
/*
* Das Array sortierSpalte ist nun sortiert. Für die nächsten Schritte wird
* der Inhalt der Spalte nicht mehr benötigt, lediglich der Index ist noch von Bedeutung.
*/
/*
* In diesem Schritt wird mittels eines Arrays in einer Schleife ein Vector mit dem Inhalt
* jeder Zeile gefüllt.
*/
Vector[] vectorZeile = new Vector[anzahlZeilen];
for(int i = 0; i < anzahlZeilen; i++)
{
vectorZeile[i] = new Vector();
for(int j = 0; j < anzahlSpalten; j++)
{
vectorZeile[i].add(this.getValueAt(i, j));
}
}
int zeile;
/*
* Nachdem alle Zeilen nun in dem Vector-Array gespeichert sind wird zeilenweise der
* Vectorinhalt dem TableModel hinzugefügt. Im gleichen Schritt wird die oberste
* Zeile gelöscht. Nach Komplett-Durchlauf dieser Schleife sind alle vorhandenen,
* unsortierten Zeilen entfernt worden und durch die sortierten ersetzt worden. *
*/
for(int i = 0; i < anzahlZeilen; i++)
{
zeile = (int) sortierSpalte[0][i];
tableModel.addRow(vectorZeile[zeile]);
tableModel.removeRow(0);
}
}
/* Nachdem die Sortierung abgeschlossen ist, wird die Variable, die die sortierteSpalte enthält,
gleich der Spalte gesetzt, die gerade sortiert wurde. */
sortierteSpalteIst = sortierteSpalteSoll;
}
/**
* Methode, um an das DefaultTableModel zu geladen (für Änderungen)
*
* @return Gibt das DefaultTableModel zurück
*/
public NichtEditierbaresDefaultTableModel getDefaultTableModel()
{
return tableModel;
}
/* Die restlichen Methoden wurden automatisch vom MouseListener implementiert, werden
jedoch nicht benötigt. */
public void mouseClicked(MouseEvent arg0)
{
}
/**
* DOCUMENT ME!
*
* @param arg0 DOCUMENT ME!
*/
public void mouseEntered(MouseEvent arg0)
{
}
/**
* DOCUMENT ME!
*
* @param arg0 DOCUMENT ME!
*/
public void mouseExited(MouseEvent arg0)
{
}
/**
* DOCUMENT ME!
*
* @param arg0 DOCUMENT ME!
*/
public void mouseReleased(MouseEvent arg0)
{
}
}