public class HidableTableColumnModel implements TableColumnModel
{
// Attribute
//----------------------------------------------------------------------------------------------
protected ArrayList<TableColumn> m_allColumns = null;
protected TableColumnModel m_delegateModel = null;
// Methoden
//----------------------------------------------------------------------------------------------
public HidableTableColumnModel( TableColumnModel delegateModel )
throws NullPointerException
{
super();
if (delegateModel == null)
throw new NullPointerException("Cannot have null table column model");
m_delegateModel = delegateModel;
m_allColumns = new ArrayList<TableColumn>( m_delegateModel.getColumnCount() );
Enumeration<TableColumn> columns = m_delegateModel.getColumns();
while (columns.hasMoreElements())
{
m_allColumns.add( columns.nextElement() );
} //while
} //Konstruktor(TableColumnModel)
public void setColumnVisible( int viewIndex, boolean visible )
{
this.setColumnVisible(
m_allColumns.get(viewIndex),
visible);
} //void setColumnVisible(int, boolean)
/**
* @brief blendet die genannte Spalte aus oder ein
*
* Diese Methode setzt die genannte Spalte auf sichtbar (einblenden) oder
* unsichtbar (ausblenden), je nach Angabe.<br>
* Wenn die Spalte nicht in einem der Modelle (dieses und das Basismodell)
* enthalten ist, geschieht nichts.
*
* @note Listener werden Ereignisse für Spalten-Entfernen und -Hinzufügen
* erhalten.
*
* @param column Spaltenobjekt, das ein-/ausgeblendet werden soll
* @param visible Angabe ob die Spalte ein- oder ausgeblendet wird
*/
public void setColumnVisible( TableColumn column, boolean visible )
{
if ( ! visible)
{
m_delegateModel.removeColumn(column);
} //if verbergen
else
{
final int visibleColumns = m_delegateModel.getColumnCount();
final int invisibleColumns = m_allColumns.size();
int idxVisible = 0;
for (int idxInvisible = 0; idxInvisible < invisibleColumns; idxInvisible++)
{
final TableColumn visibleColumn = ( idxVisible < visibleColumns
? m_delegateModel.getColumn(idxVisible)
: null);
final TableColumn testColumn = m_allColumns.get(idxInvisible);
if (testColumn.equals(column))
{
if ( ! column.equals(visibleColumn))
{
m_delegateModel.addColumn(column);
m_delegateModel.moveColumn(
m_delegateModel.getColumnCount() -1,
idxVisible);
} //if ! sichtbare Spalte
return;
} //if
if (testColumn.equals(visibleColumn))
idxVisible++;
} //for
} //if zeigen
} //void setColumnVisible(TableColumn, boolean)
/**
* @brief zeigt alle Spalten im Modell an
*
* Diese Methode blendet alle Spalte ein.
*/
public void setAllColumnsVisible()
{
final int totalSize = m_allColumns.size();
for (int idxColumn = 0; idxColumn < totalSize; idxColumn++)
{
final TableColumn visibleColumn = ( idxColumn < m_delegateModel.getColumnCount()
? m_delegateModel.getColumn(idxColumn)
: null);
final TableColumn invisibleColumn = m_allColumns.get(idxColumn);
if ( ! invisibleColumn.equals(visibleColumn))
{
m_delegateModel.addColumn(invisibleColumn);
m_delegateModel.moveColumn(
m_delegateModel.getColumnCount() -1,
idxColumn);
} //if ungleich
} //for
} //void setAllColumnsVisible()
/**
* @brief Getter für Spalte anhand des Modell-Indizes
*
* Ermittelt das Spaltenobjekt aus der Gesamtmenge der Spalten (auch jene, die nicht
* sichtbar sind), das dem gegebenen Modellindex (vom Tabellenmodell) entspricht.
*
* @param modelIndex Index des Tabellenmodells der Spalte, die erfragt ist
* @return (erste) gefundene Spalte oder <code>null</code>
*/
public TableColumn getColumnByModelIndex( int modelIndex )
{
for (int idxColumn = 0; idxColumn < m_allColumns.size(); idxColumn++)
{
final TableColumn column = m_allColumns.get(idxColumn);
if (column.getModelIndex() == modelIndex)
return column;
} //for
return null;
} //TableColumn getColumnByModelIndex(int)
/**
* @brief gibt an, ob Spalte sichtbar ist, oder nicht
*
* Diese Methode gibt an, ob die gegebene Spalte sichtbar ist, oder nicht. Sprich
* ob sie ausgeblendet wurde (in diesem Fall lautet die Rückgabe <code>false</code>).
*
* @param column Spaltenobjekt
* @return <code>true</code> wenn diese Spalte eingeblendet ist
*/
public boolean isColumnVisible( TableColumn column )
{
for (int i = 0; i < m_delegateModel.getColumnCount(); i++)
{
if (m_delegateModel.getColumn(i).equals(column))
return true;
} //for
return false;
} //boolean isColumnVisible(TableColumn)
/**
* @brief Getter für Anzahl der Spalten
*
* Gibt an, wie viele Spalten dieses Modell hat. Über den Parameter lässt sich
* steuern, ob nur die sichtbaren, oder auch die ausgeblendeten Spalten
* gezählt werden.
*
* @param visibleOnly wenn <code>true</code>, werden nur die sichtbaren
* Spalten gezählt
* @return Anzahl der Spalten, je nach Parameter alle oder nur die
* sichtbaren
*
* @see getColumnCount()
*/
public int getColumnCount( boolean visibleOnly )
{
if (visibleOnly)
return m_delegateModel.getColumnCount();
else
return m_allColumns.size();
} //int getColumnCount(boolean)
/**
* @brief gibt eine Aufzählung der Spalten zurück
*
* Diese Methode gibt eine Aufzählung der Spalten des Modells zurück. Über den
* Parameter lässt sich steuern, ob alle Spalten (<code>= false</code>) oder nur
* die sichtbaren (<code>= true</code>) angegeben werden sollen.<br>
* Bei <code>true</code> wird das delegierte Modell befragt.
*
* @param visibleOnly wenn <code>true</code>, werden nur die sichtbaren
* Spalten zurückgegeben
* @return Aufzählung über die Spalten, je nach Parameter alle oder nur die
* sichtbaren
*
* @see getColumns()
*/
public Enumeration<TableColumn> getColumns( boolean visibleOnly )
{
if (visibleOnly)
{
return m_delegateModel.getColumns();
} //if sichtbare
else
{
return new Enumeration<TableColumn>()
{
private int m_index = 0;
@Override
public TableColumn nextElement()
{
return m_allColumns.get(m_index++);
} //TableColumn nextElement()
@Override
public boolean hasMoreElements()
{
return (m_index < m_allColumns.size());
} //boolean hasMoreElements()
};
} //if alle
} //Enumeration<TableColumn> getColumns(boolean)
/**
* @brief Getter für Index der ersten Spalte mit gegebenen
* Identifikator
*
* Diese Methode ermittelt den (Anzeige-)Index der ersten Spalte mit dem
* gegebenen Identifikator. Es wird über die <code>equals()</code>-Methode
* verglichen.<br>
* Über den zweiten Parameter kann man steuern, ob nur alle sichtbaren oder auch
* die ausgeblendeten Spalten geprüft werden.
*
* @param identifier Identifikations-Objekt der gesuchten Spalte
* @param visibleOnly Angabe ob nur die sichtbaren Spalten durchsucht werden
* @return Index der gefundenen Spalte oder eine Ausnahme
*
* @throws IllegalArgumentException
* Wenn der Identifikator <code>null</code> ist, oder keine Spalte mit
* dem gegebenen Identifikator gefunden wurde.
*
* @see getColumnIndex(Object)
*/
public int getColumnIndex( Object identifier, boolean visibleOnly )
throws IllegalArgumentException
{
if (identifier == null)
throw new IllegalArgumentException("Identifiert cannot be null");
Enumeration<TableColumn> columns = this.getColumns(visibleOnly);
int index = 0;
while (columns.hasMoreElements())
{
final Object id = columns.nextElement().getIdentifier();
if (identifier.equals(id))
return index;
index++;
} //while
throw new IllegalArgumentException("Identifier "+identifier+" not found");
} //int getColumnIndex(Object, boolean)
/**
* @brief Getter für Spalte am Index
*
* Diese Methode ermittelt die Spalte am gegebenen (Anzeige-)Index. Über den
* zweiten Parameter lässt sich steuern, ob alle sichtbaren oder auch die
* ausgeblendeten Spalten betrachtet werden.
*
* @param columnIndex Index der gesuchten Spalte. Der Index entspricht dem
* Anzeigeindex in der Tabelle
* @param visibleOnly Angabe ob nur sichtbare Spalten geprüft werden
* @return gefundene Spalte
*
* @exception IndexOutOfBoundsException
* Wenn der gegeben Index außerhalb des gültigen Bereichs liegt.
*
* @see getColumn(int)
*/
public TableColumn getColumn( int columnIndex, boolean visibleOnly )
{
if (visibleOnly)
return m_delegateModel.getColumn(columnIndex);
else
return m_allColumns.get(columnIndex);
} //TableColumn getColumn(int, boolean)
/**
* @brief Methode für bequeme Aktionen
*
* Diese Methode erstellt (bei jedem Aufruf neu) eine Menge von Aktionen, die für jede
* der gesetzen Spalten (auch unsichtbare) eine selektierte Aktion darstellt, um
* sie ein- und auszublenden:
* @code
* HidableTableColumnModel cModel = ...;
* JPopupMenu popup = new JPopupMenu("Hide Menu");
* Action[] actions = cModel.createColumnActions();
* for (Action act : actions)
* {
* popup.add(new JCheckBoxMenuItem(act));
* } //for
* myTable.setComponentPopupMenu(popup);
* @endcode
*
* @note Die Aktionen sind <i>nicht</i> serialisierbar!
*
* @return Feld mit Aktionen, pro Spalte eine eigene
*/
@SuppressWarnings("serial")
public Action[] createColumnActions()
{
final Action[] actions = new Action[ m_allColumns.size() ];
for (int i = 0; i < m_allColumns.size(); i++)
{
final TableColumn col = m_allColumns.get(i);
final Action act = new AbstractAction()
{
final private TableColumn internalColumn = col;
{
this.putValue(
SELECTED_KEY,
HidableTableColumnModel.this.isColumnVisible(col));
this.putValue(NAME,
col.getHeaderValue());
}
@Override
public void actionPerformed( ActionEvent event )
{
HidableTableColumnModel.this.setColumnVisible(
internalColumn,
((Boolean) this.getValue(SELECTED_KEY)).booleanValue());
} //void actionPerformed(ActionEvent)
};
actions[i] = act;
} //for
return actions;
} //Action[] createColumnActions()
// Table Column Model Methoden
//----------------------------------------------------------------------------------------------
/**
* @brief fügt neue Spalte hinzu
*
* Diese Methode fügt die gegebene Spalte dem Modell an letzter Stelle hinzu.
*
* @param column neues Spaltenobjekt
*/
@Override
public void addColumn( TableColumn column )
{
m_allColumns.add(column);
m_delegateModel.addColumn(column);
} //void addColumn(TableColumn)
/**
* @brief entfernt die Spalte aus dem Modell
*
* Diese Methode entfernt die gegebene Spalte aus dem Modell.
*
* @param column zu entfernende Spalte
*/
@Override
public void removeColumn( TableColumn column )
{
m_allColumns.remove(column);
m_delegateModel.removeColumn(column);
} //void removeColumn(TableColumn)
/**
* @brief verschiebt Spalte innerhalb der Tabelle
*
* Diese Methode verschiebt die Spalte an Stelle <code>oldIndex</code> nach
* <code>newIndex</code>. Verwendet werden hier die Anzeigeindizes.
*
* @param oldIndex Anzeigeindex der Spalte, die verschoben werden soll
* @param newIndex Anzeigeindex des Ortes, an den die Spalte verschoben
* wird
*
* @throws IllegalArgumentException
* Wenn einer der Indizes nicht im gültigen bereich liegt.
*/
@Override
public void moveColumn( int oldIndex, int newIndex )
throws IndexOutOfBoundsException
{
final int size = m_delegateModel.getColumnCount();
if ( oldIndex < 0 || oldIndex >= size
|| newIndex < 0 || newIndex >= size)
{
throw new IndexOutOfBoundsException(
"At least one index is invalid: '"
+oldIndex
+"' or '"
+newIndex
+"' (valid range is [0, "
+size
+"])");
} //if Fehler
final TableColumn oldColumn = m_delegateModel.getColumn(oldIndex);
final TableColumn newColumn = m_delegateModel.getColumn(newIndex);
final int idxOld = m_allColumns.indexOf(oldColumn);
final int idxNew = m_allColumns.indexOf(newColumn);
if (oldIndex != newIndex)
{
m_allColumns.remove(idxOld);
m_allColumns.add(idxNew, oldColumn);
} //if
m_delegateModel.moveColumn(oldIndex, newIndex);
} //void moveColumn(int, int)
/**
* @brief fügt Listener hinzu
*
* Der Listener wird an das delegierte Modell hinzugefügt.
*
* @param listener neuer Listener
*/
@Override
public void addColumnModelListener( TableColumnModelListener listener )
{
m_delegateModel.addColumnModelListener(listener);
} //void addColumnModelListener(TableColumnModelListener)
/**
* @brief entfernt Listener
*
* Der Listener wird vom delegierten Modell entfernt.
*
* @param listener Listener der entfernt wird
*/
@Override
public void removeColumnModelListener( TableColumnModelListener listener )
{
m_delegateModel.removeColumnModelListener(listener);
} //void removeColumnModelListener(TableColumnModelListener)
/**
* @brief Getter für Spalte am gegebenen Index
*
* Diese Methode ermittelt die Spalte am gegeben Index. Verwendet werden
* nur sichtbare Spalten.
*
* @param columnIndex Index der gesuchten Spalte. Verwendet wird hier
* der Anzeigeindex der Tabelle.
* @return gefundene Spalte
*
* @exception IndexOutOfBoundsException
* Wenn der gegeben Index außerhalb des gültigen Bereichs liegt.
*
* @see getColumn(int, boolean)
*/
@Override
public TableColumn getColumn( int columnIndex )
{
return this.getColumn(columnIndex, true);
} //TableColumn getColumn(int)
/**
* @brief Getter für Spaltenzahl
*
* Gibt die Anzahl der sichtbaren (!) Spalten zurück.
* @return Anzahl der sichtbaren Spalten
*
* @see getColumnCount(boolean)
*/
@Override
public int getColumnCount()
{
return this.getColumnCount(true);
} //int getColumnCount()
/**
* @brief ermittelt Index der Spalte durch Identifikator
*
* Diese Methode ermittelt den Index der Spalte über alle sichtbaren
* Spalten. Dazu wird intern #getColumnIndex(Object, boolean) verwendet.
*
* @param identifier Identifikations-Objekt der gesuchten Spalte
* @return Index der gefundenen Spalte oder eine Ausnahme
*
* @throws IllegalArgumentException
* Wenn der Identifikator <code>null</code> ist, oder keine Spalte mit
* dem gegebenen Identifikator gefunden wurde.
*
* @see getColumnIndex(Object, boolean)
*/
@Override
public int getColumnIndex( Object identifier ) throws IllegalArgumentException
{
return this.getColumnIndex(identifier, true);
} //int getColumnIndexObject)
/**
* @brief Getter für Spalte an X-Position
*
* Diese Methode ermittelt über das delegierte Modell den Spaltenindex
* an der gegebenen X-Position.
*
* @param position erfragte X-Position, meist Pixelwerte
* @return Index der Spalte an der Position
*/
@Override
public int getColumnIndexAtX( int position )
{
return m_delegateModel.getColumnIndexAtX(position);
} //int getColumnIndexAtX(int)
/**
* @brief Getter für Spaltenabstand
*
* Gibt den Abstand der Spalten zurück. Dies wird vom delegierten
* Modell verwaltet.
*
* @return Abstand der Spalten in Pixeln
*
* @see setColumnMargin(int)
*/
@Override
public int getColumnMargin()
{
return m_delegateModel.getColumnMargin();
} //int getColumnMargin()
/**
* @brief gibt an, ob Spaltenselektion erlaubt ist
*
* Diese Methode gibt zurück, ob die Selektion ganzer
* Spalten erlaubt ist, oder nicht.
*
* @return <code>true</code> wenn Spaltenselektion erlaubt ist
*
* @see setColumnSelectionAllowed(boolean)
*/
@Override
public boolean getColumnSelectionAllowed()
{
return m_delegateModel.getColumnSelectionAllowed();
} //boolean getColumnSelectionAllowed()
/**
* @brief Getter für alle Spalten
*
* Diese Methode gibt eine Aufzählung über alle sichtbaren
* Spalten zurück.
*
* @return Aufzählung mit allen sichtbaren Spalten
*
* @see getColumns(boolean)
*/
@Override
public Enumeration<TableColumn> getColumns()
{
return this.getColumns(true);
} //Enumeration<TableColumn> getColumns()
/**
* @brief ermittelt die Anzahl der selektierten Spalten
*
* Ermittelt die Anzahl der selektierten Spalten über das
* delegierte Modell.
*
* @return Anzahl selektierter Spalten
*/
@Override
public int getSelectedColumnCount()
{
return m_delegateModel.getSelectedColumnCount();
} //int getSelectedColumnCount()
/**
* @brief ermittelt Indizes der selektierten Spalten
*
* Diese Methode ermittelt die Indizes der selektierten
* Spalten über das delegierte Modell.
*
* @return Feld mit den Indizes der selektierten Spalten, oder
* leeres Array
*/
@Override
public int[] getSelectedColumns()
{
return m_delegateModel.getSelectedColumns();
} //int[] getSelectedColumns()
/**
* @brief Getter für Selektionsmodell
*
* Gibt das Selektionsmodell der delegierten Modells zurück.
*
* @return Selektionsmodell
*/
@Override
public ListSelectionModel getSelectionModel()
{
return m_delegateModel.getSelectionModel();
} //ListSelectionModel getSelectionModel()
/**
* @brief ermittelt vollständige Breite der Spalten
*
* Diese Methode ermittelt (über das delegierte Modell) die vollständige
* Breite der Spalten in Pixeln.
*
* @return Breite aller (sichtbaren) Spalten in Pixeln
*/
@Override
public int getTotalColumnWidth()
{
return m_delegateModel.getTotalColumnWidth();
} //int getTotalColumnWidth()
/**
* @brief Setter für Spaltenabstand
*
* Übernimmt den neuen Spaltenabstand in Pixeln, welcher an das
* delegierte Modell weitergetragen wird.
*
* @param newMargin neuer Spaltenabstand
*
* @see getColumnMargin()
*/
@Override
public void setColumnMargin( int newMargin )
{
m_delegateModel.setColumnMargin(newMargin);
} //void setColumnMargin(int)
/**
* @brief erlaubt/verbietet Spaltenselektion
*
* Über diese Methode kann man die Selektion ganzer Spalten
* erlauben, bzw. verbieten.
*
* @param flag Angabe ob Selektion erlaubt ist, oder nicht
*
* @see getColumnSelectionAllowed()
*/
@Override
public void setColumnSelectionAllowed( boolean flag )
{
m_delegateModel.setColumnSelectionAllowed(flag);
} //void setColumnSelectionAllowed(boolean)
/**
* @brief Setter für Selektionsmodell
*
* Übernimmt das neue Selektionsmodell für das delegierte Spaltenmodell.
*
* @param model neues Selektionsmodell
*
* @see getSelectionModel()
*/
@Override
public void setSelectionModel( ListSelectionModel model )
{
m_delegateModel.setSelectionModel(model);
} //void setSelectionModel(ListSelectionModel)
} //class HidableTableColumnModel