/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>,
Patick J. McSweeney <pjmcswee@syr.edu>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.ui.components;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.WindowConstants;
import javax.swing.text.View;
import org.apache.commons.codec.binary.Base64;
import org.openide.awt.StatusDisplayer;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.openide.windows.WindowManager;
/**
*
* @author Mathieu Bastian
* @author Patick J. McSweeney
*/
class ReportSelection implements Transferable {
private static ArrayList flavors = new ArrayList();
static {
try {
flavors.add(new DataFlavor("text/html;class=java.lang.String"));
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
private String html;
/**
*
* @param html
*/
public ReportSelection(String html) {
this.html = html;
String newHTML = new String();
String[] result = html.split("file:");
boolean first = true;
for (int i = 0; i < result.length; i++) {
if (result[i].contains("</IMG>")) {
String next = result[i];
//System.out.println("> " + next);
String[] elements = next.split("\"");
String filename = elements[0];
ByteArrayOutputStream out = new ByteArrayOutputStream();
File file = new File(filename);
try {
BufferedImage image = ImageIO.read(file);
ImageIO.write((RenderedImage) image, "PNG", out);
} catch (Exception e) {
e.printStackTrace();
}
byte[] imageBytes = out.toByteArray();
String base64String = Base64.encodeBase64String(imageBytes);
if (!first) {
newHTML += "\"";
}
first = false;
newHTML += "data:image/png;base64," + base64String;
for (int j = 1; j < elements.length; j++) {
newHTML += "\"" + elements[j];
}
} else {
newHTML += result[i];
}
}
this.html = newHTML;
}
/**
*
* @return
*/
public DataFlavor[] getTransferDataFlavors() {
return (DataFlavor[]) flavors.toArray(new DataFlavor[flavors.size()]);
}
/**
*
* @param flavor
* @return
*/
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavors.contains(flavor);
}
/**
*
* @param flavor
* @return
* @throws java.awt.datatransfer.UnsupportedFlavorException
*/
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (String.class.equals(flavor.getRepresentationClass())) {
return html;
}
throw new UnsupportedFlavorException(flavor);
}
}
/**
*
* @author pjmcswee
*/
public class SimpleHTMLReport extends javax.swing.JDialog implements Printable {
private String mHTMLReport;
public SimpleHTMLReport(java.awt.Frame parent, String html) {
super(parent, false);
mHTMLReport = html;
initComponents();
displayPane.setContentType("text/html;");
displayPane.setText(this.mHTMLReport);
Dimension dimension = new Dimension(700, 600);
setPreferredSize(dimension);
displayPane.setCaretPosition(0);
setTitle("HTML Report");
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
pack();
setLocationRelativeTo(parent);
setVisible(true);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
displayPane = (javax.swing.JEditorPane)(new JHTMLEditorPane());
closeButton = new javax.swing.JButton();
jToolBar1 = new javax.swing.JToolBar();
printButton = new javax.swing.JButton();
copyButton = new javax.swing.JButton();
saveButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle(org.openide.util.NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.title")); // NOI18N
jScrollPane1.setViewportView(displayPane);
closeButton.setText(org.openide.util.NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.closeButton.text")); // NOI18N
closeButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
jToolBar1.setFloatable(false);
jToolBar1.setRollover(true);
printButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/ui/components/resources/print.png"))); // NOI18N
printButton.setText(org.openide.util.NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.printButton.text")); // NOI18N
printButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
printButtonActionPerformed(evt);
}
});
jToolBar1.add(printButton);
copyButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/ui/components/resources/copy.gif"))); // NOI18N
copyButton.setText(org.openide.util.NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.copyButton.text")); // NOI18N
copyButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyButtonActionPerformed(evt);
}
});
jToolBar1.add(copyButton);
saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/gephi/ui/components/resources/save.png"))); // NOI18N
saveButton.setText(org.openide.util.NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.saveButton.text")); // NOI18N
saveButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveButtonActionPerformed(evt);
}
});
jToolBar1.add(saveButton);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 194, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(closeButton)
.addContainerGap())
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(closeButton)
.addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void printButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_printButtonActionPerformed
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat pf = pjob.defaultPage();
pjob.setPrintable(this, pf);
try {
if (pjob.printDialog()) {
pjob.print();
}
} catch (PrinterException e) {
e.printStackTrace();
}
}//GEN-LAST:event_printButtonActionPerformed
private final String LAST_PATH = "SimpleHTMLReport_Save_Last_Path";
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
final String html = this.mHTMLReport;
final String path = NbPreferences.forModule(SimpleHTMLReport.class).get(LAST_PATH, null);
JFileChooser fileChooser = new JFileChooser(path);
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = fileChooser.showOpenDialog(WindowManager.getDefault().getMainWindow());
if (result == JFileChooser.APPROVE_OPTION) {
final File destinationFolder = fileChooser.getSelectedFile();
NbPreferences.forModule(SimpleHTMLReport.class).put(LAST_PATH, destinationFolder.getAbsolutePath());
Thread saveReportThread = new Thread(new Runnable() {
public void run() {
try {
saveReport(html, destinationFolder);
StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(SimpleHTMLReport.class, "SimpleHTMLReport.status.saveSuccess", destinationFolder.getName()));
} catch (IOException e) {
e.printStackTrace();
}
}
}, "SaveReportTask");
saveReportThread.start();
}
}//GEN-LAST:event_saveButtonActionPerformed
private void saveReport(String html, File destinationFolder) throws IOException {
if (!destinationFolder.exists()) {
destinationFolder.mkdir();
}
//Find images location
String imgRegex = "<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>";
Pattern pattern = Pattern.compile(imgRegex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(html);
StringBuffer replaceBuffer = new StringBuffer();
while (matcher.find()) {
String fileAbsolutePath = matcher.group(1);
if (fileAbsolutePath.startsWith("file:")) {
fileAbsolutePath = fileAbsolutePath.replaceFirst("file:", "");
}
File file = new File(fileAbsolutePath);
if (file.exists()) {
copy(file, destinationFolder);
}
//Replace temp path
matcher.appendReplacement(replaceBuffer, "<IMG SRC=\"" + file.getName() + "\">");
}
matcher.appendTail(replaceBuffer);
//Write HTML file
File htmlFile = new File(destinationFolder, "report.html");
FileOutputStream outputStream = new FileOutputStream(htmlFile);
OutputStreamWriter out = new OutputStreamWriter(outputStream, "UTF-8");
out.append(replaceBuffer.toString());
out.flush();
out.close();
outputStream.close();
}
private void copyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyButtonActionPerformed
Toolkit toolkit = Toolkit.getDefaultToolkit();
try {
toolkit.getSystemClipboard().setContents(new ReportSelection(this.mHTMLReport), null);
} catch (Exception e) {
e.printStackTrace();
}
}//GEN-LAST:event_copyButtonActionPerformed
/**
*
* @param evt
*/
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
dispose(); // TODO add your handling code here:
}//GEN-LAST:event_closeButtonActionPerformed
/**
* @param args the command line arguments
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
SimpleHTMLReport dialog = new SimpleHTMLReport(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
* */
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton closeButton;
private javax.swing.JButton copyButton;
private javax.swing.JEditorPane displayPane;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JToolBar jToolBar1;
private javax.swing.JButton printButton;
private javax.swing.JButton saveButton;
// End of variables declaration//GEN-END:variables
/**
*
* @param graphics
* @param pageFormat
* @param pageIndex
* @return
*/
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
boolean last = false;
try {
View rootView = displayPane.getUI().getRootView(displayPane);
double scaleX = pageFormat.getImageableWidth() / displayPane.getMinimumSize().getWidth();
scaleX = Math.min(scaleX, 1.0);
double scaleY = scaleX;
int end = (int) (pageIndex * ((1.0f / scaleY) * (double) pageFormat.getImageableHeight()));
Rectangle allocation = new Rectangle(0,
-end,
(int) pageFormat.getImageableWidth(),
(int) pageFormat.getImageableHeight());
((Graphics2D) graphics).scale(scaleX, scaleY);
graphics.setClip((int) (pageFormat.getImageableX() / scaleX),
(int) (pageFormat.getImageableY() / scaleY),
(int) (pageFormat.getImageableWidth() / scaleX),
(int) (pageFormat.getImageableHeight() / scaleY));
((Graphics2D) graphics).translate(((Graphics2D) graphics).getClipBounds().getX(),
((Graphics2D) graphics).getClipBounds().getY());
rootView.paint(graphics, allocation);
last = end > displayPane.getUI().getPreferredSize(displayPane).getHeight();
if ((last)) {
return Printable.NO_SUCH_PAGE;
}
} catch (Exception e) {
e.printStackTrace();
}
return Printable.PAGE_EXISTS;
}
public void copy(File source, File dest) throws IOException {
FileChannel in = null, out = null;
try {
if (dest.isDirectory()) {
dest = new File(dest, source.getName());
}
in = new FileInputStream(source).getChannel();
out = new FileOutputStream(dest).getChannel();
long size = in.size();
MappedByteBuffer buf = in.map(FileChannel.MapMode.READ_ONLY, 0, size);
out.write(buf);
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}