/*
* 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.print;
import java.awt.Component;
import java.awt.Desktop;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import net.bull.javamelody.swing.table.MBasicTable;
/**
* Classe d'impression et d'export.
*
* @author Emeric Vernat
*/
public abstract class MPrinter {
// instance du fileChooser (pour export)
private static JFileChooser fileChooser;
/**
* Constructeur.
*/
protected MPrinter() {
super();
}
/**
* Construit le titre à inclure dans l'impression/export.
*
* @param component
* Component
* @return String
*/
protected String buildTitle(final Component component) {
Component current = component;
final StringBuilder title = new StringBuilder();
while (current != null) {
final String currentTitle = getTitleIfKnownComponent(current);
if (currentTitle != null && currentTitle.length() != 0) {
if (title.length() != 0) {
title.insert(0, " - ");
}
title.insert(0, currentTitle);
}
current = current.getParent();
}
return title.length() != 0 ? title.toString() : null;
}
private String getTitleIfKnownComponent(Component current) {
if (current instanceof JTabbedPane) {
final JTabbedPane tabbedPane = (JTabbedPane) current;
return tabbedPane.getTitleAt(tabbedPane.getSelectedIndex());
} else if (current instanceof JFrame) {
return ((JFrame) current).getTitle();
} else if (current instanceof JDialog) {
return ((JDialog) current).getTitle();
}
return null;
}
/**
* Renvoie le texte de la cellule de cette JTable à la ligne et la colonne spécifiée.
*
* @return String
* @param table
* MBasicTable
* @param row
* int
* @param column
* int
*/
protected String getTextAt(final MBasicTable table, final int row, final int column) {
String text = table.getTextAt(row, column);
// suppression de tags éventuellements présents (par ex. avec un MultiLineTableCellRenderer)
if (text != null && text.startsWith("<html>")) {
text = text.replaceFirst("<html>", "");
text = text.replaceFirst("<center>", "");
text = text.replaceAll("<br/>", "\n");
text = text.replaceAll(" ", " ");
text = text.replaceFirst("<font color='#[0-9]*+'>", "");
}
return text;
}
/**
* Renvoie la valeur de la cellule de cette JTable à la ligne et la colonne spécifiée.
*
* @return String
* @param table
* MBasicTable
* @param row
* int
* @param column
* int
*/
protected Object getValueAt(final MBasicTable table, final int row, final int column) {
return table.getModel().getValueAt(row, column);
}
/**
* Renvoie la boîte de dialogue swing de choix du fichier d'export. (Initialisée pour s'ouvrir sur le répertoire courant user.dir).
*
* @return JFileChooser
*/
public static synchronized JFileChooser getFileChooser() { // NOPMD
if (fileChooser == null) {
final String currentDirectory = System.getProperty("user.dir");
fileChooser = new JFileChooser(currentDirectory);
}
return fileChooser;
}
/**
* Choix du fichier pour un export.
*
* @return File
* @param table
* JTable
* @param extension
* String
* @throws IOException
* Erreur disque
*/
protected File chooseFile(final JTable table, final String extension) throws IOException {
final JFileChooser myFileChooser = getFileChooser();
final MExtensionFileFilter filter = new MExtensionFileFilter(extension);
myFileChooser.addChoosableFileFilter(filter);
String title = buildTitle(table);
if (title != null) {
// on remplace par des espaces les caractères interdits dans les noms de fichiers : \ / : * ? " < > |
final String notAllowed = "\\/:*?\"<>|";
final int notAllowedLength = notAllowed.length();
for (int i = 0; i < notAllowedLength; i++) {
title = title.replace(notAllowed.charAt(i), ' ');
}
myFileChooser.setSelectedFile(new File(title));
}
// l'extension sera ajoutée ci-dessous au nom du fichier
try {
final Component parent = table.getParent() != null ? table.getParent() : table;
if (myFileChooser.showSaveDialog(parent) == JFileChooser.APPROVE_OPTION) {
String fileName = myFileChooser.getSelectedFile().getCanonicalPath();
if (!fileName.endsWith('.' + extension)) {
fileName += '.' + extension; // NOPMD
}
return new File(fileName);
}
return null;
} finally {
myFileChooser.removeChoosableFileFilter(filter);
}
}
/**
* Retourne le fichier de sortie, par défaut on ouvre la boîte de dialogue de choix du fichier.
*
* @return File
* @param table
* JTable
* @throws IOException
* Erreur disque
*/
protected File getFile(final JTable table) throws IOException {
return chooseFile(table, getFileExtension());
}
/**
* Méthode abstraite assurant le polymorphisme des instances.
*
* @param table
* MBasicTable
* @param outputStream
* OutputStream
* @throws IOException
* Erreur disque
*/
public abstract void print(MBasicTable table, OutputStream outputStream) throws IOException;
/**
* Méthode abstraite : les instances doivent renvoyer leur nom.
*
* @return String
*/
public abstract String getName();
/**
* Méthode abstraite : les instances doivent renvoyer l'extension du fichier exporté.
*
* @return String
*/
public abstract String getFileExtension();
/**
* Méthode abstraite : les instances doivent renvoyer l'icône représentant le type.
*
* @return Icon
*/
public abstract Icon getIcon();
/**
* Impression/export de la table.
*
* @param table
* MBasicTable
* @throws IOException
* Erreur disque
*/
public void print(final MBasicTable table) throws IOException {
final File file = getFile(table);
if (file != null) {
try (final OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(
file))) {
print(table, outputStream);
}
showDocument(file);
}
}
/**
* Affiche le document. <br/>
* Les implémentations peuvent surcharger cette méthode.
*
* @param targetFile
* File
* @throws IOException
* Erreur disque
*/
protected void showDocument(final File targetFile) throws IOException {
try {
Desktop.getDesktop().open(targetFile);
} catch (final IOException e) {
throw new IOException("Is there an associated application for \""
+ targetFile.getName() + "\"?\n" + e.getMessage(), e);
}
// on pourrait imprimer le fichier directement (par exemple CSV avec Excel) en supposant que Desktop.getDesktop().isDesktopSupported()
// et Desktop.getDesktop().isSupported(Desktop.Action.PRINT) retournent true
// ce qui est le cas en Windows XP SP2 (et Java 1.6)
// Desktop.getDesktop().print(targetFile);
}
/**
* Retourne le nom pour affichage.
*
* @return String
*/
@Override
public String toString() {
return getName();
}
}