/*
* Copyright 2008-2014 by Emeric Vernat
*
* This file is part of Java Melody.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bull.javamelody.swing.table;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import net.bull.javamelody.swing.print.MClipboardPrinter;
/**
* Composant Table, qui utilise une API typée pour la liste des valeurs et qui utilise les String pour définir les valeurs dans les colonnes.
*
* @param <T>
* Type des valeurs de la liste
* @author Emeric Vernat
*/
public class MTable<T> extends MListTable<T> {
static final Color BICOLOR_LINE = Color.decode("#E7E7E7");
private static final long serialVersionUID = 1L;
@SuppressWarnings("all")
private static final KeyAdapter CLIPBOARD_KEY_LISTENER = new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent event) {
if (event.getSource() instanceof MTable) {
final MTable<?> table = (MTable<?>) event.getSource();
final int keyCode = event.getKeyCode();
final int modifiers = event.getModifiers();
if ((modifiers & java.awt.Event.CTRL_MASK) != 0 && keyCode == KeyEvent.VK_C) {
event.consume();
new MClipboardPrinter().print(table, null);
}
}
}
};
@SuppressWarnings("all")
private static final MouseAdapter POPUP_MENU_MOUSE_LISTENER = new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent event) {
if (event.isPopupTrigger() || SwingUtilities.isRightMouseButton(event)
&& event.getComponent() instanceof MTable) {
final MBasicTable table = (MBasicTable) event.getComponent();
final TablePopupMenu tablePopupMenu = new TablePopupMenu(table);
tablePopupMenu.show(table, event.getX(), event.getY());
}
}
};
/**
* Constructeur.
*/
public MTable() {
// on utilise le modèle par défaut créé par la méthode createDefaultDataModel() ci-dessus
this(null);
}
/**
* Constructeur.
*
* @param dataModel
* Modèle pour les données
*/
protected MTable(final MListTableModel<T> dataModel) {
super(dataModel);
// la table ne crée pas automatiquement les colonnes à partir du dataModel,
// et les colonnes seront définies en utilisant la méthode addColumn ci-dessous
setAutoCreateColumnsFromModel(false);
// le rowSorter sera automatiquement ajouté lors des appels à setModel (la classe MListTableModel définit getColumnClass à partir des données)
setAutoCreateRowSorter(true);
// fond de couleur blanc (plutôt que gris en look and feel Nimbus ; utile pour le rendu des cases à cocher dans le tableau)
setBackground(Color.WHITE);
// listener pour surcharger la copie dans presse-papier (format pour Excel et non format par défaut de Swing)
addKeyListener(CLIPBOARD_KEY_LISTENER);
// listener pour afficher le popup menu
addMouseListener(POPUP_MENU_MOUSE_LISTENER);
}
@Override
protected TableModel createDefaultDataModel() {
return new MTableModel<T>(this);
}
/**
* Ajoute une colonne dans la table.
*
* @param attribute
* Nom de l'attribut des objets à afficher dans la colonne<br/>
* @param libelle
* Libellé à afficher en entête de la colonne
* @return this (fluent)
*/
public MTable<T> addColumn(final String attribute, final String libelle) {
final int modelIndex = getColumnCount();
final TableColumn tableColumn = new TableColumn(modelIndex);
// on met l'énumération de l'attribut comme identifier dans le TableColumn pour s'en servir dans MTableModel
tableColumn.setIdentifier(attribute);
if (libelle == null) {
// on prend par défaut l'attribut si le libellé n'est pas précisé,
tableColumn.setHeaderValue(attribute);
} else {
// le libellé a été précisé pour l'entête de cette colonne
tableColumn.setHeaderValue(libelle);
}
// ajoute la colonne dans la table
super.addColumn(tableColumn);
return this;
}
/**
* Méthode typée pour définir un renderer spécifique pour les cellules d'une colonne dans la table.
*
* @param attribute
* Nom de l'attribut des objets pour une colonne existante
* @param cellRenderer
* Renderer des cellules dans cette colonne
*/
public void setColumnCellRenderer(final String attribute, final TableCellRenderer cellRenderer) {
getColumn(attribute).setCellRenderer(cellRenderer);
}
/** {@inheritDoc} */
@Override
public Component prepareRenderer(final TableCellRenderer renderer, final int rowIndex,
final int vColIndex) {
// Surcharge pour la gestion des lignes de couleurs alternées.
final Component component = super.prepareRenderer(renderer, rowIndex, vColIndex);
if (BICOLOR_LINE != null && !isRowSelected(rowIndex)) {
if (rowIndex % 2 == 0) {
component.setBackground(BICOLOR_LINE);
} else {
component.setBackground(getBackground());
}
}
return component;
}
}