/* * The MIT License * * Copyright 2016 Pawel Marynowski. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package pattypan.panes; import com.drew.imaging.ImageMetadataReader; import com.drew.imaging.ImageProcessingException; import com.drew.metadata.Directory; import com.drew.metadata.Metadata; import com.drew.metadata.exif.ExifSubIFDDirectory; import java.awt.Desktop; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; import java.util.logging.Level; import javafx.scene.control.Hyperlink; import javafx.scene.layout.Region; import javafx.scene.text.TextAlignment; import javafx.scene.text.TextFlow; import javafx.stage.Stage; import jxl.CellView; import jxl.Workbook; import jxl.read.biff.BiffException; import jxl.write.Label; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import pattypan.Session; import pattypan.Settings; import pattypan.Template; import pattypan.TemplateField; import pattypan.Util; import pattypan.elements.WikiButton; import pattypan.elements.WikiLabel; import pattypan.elements.WikiPane; import pattypan.elements.WikiTextField; public class CreateFilePane extends WikiPane { Stage stage; WikiLabel descLabel; WikiTextField fileName = new WikiTextField("").setPlaceholder("create-file-filename").setWidth(300); WikiButton createButton = new WikiButton("create-file-button", "primary").setWidth(300); public CreateFilePane(Stage stage) { super(stage, 1.0); this.stage = stage; setContent(); setActions(); } public WikiPane getContent() { return this; } private WikiPane setContent() { addElement("generic-summary", "header"); addElement(Util.text("create-file-summary", Session.FILES.size(), Session.DIRECTORY.getName()), 40); addElement(fileName); addElement(new Region()); addElement(createButton); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss"); fileName.setText("pattypan " + sdf.format(new Date())); prevButton.linkTo("ChooseColumnsPane", stage); nextButton.setVisible(false); return this; } private WikiPane setActions() { fileName.textProperty().addListener((observable, oldValue, newValue) -> { createButton.setDisable(newValue.isEmpty()); }); createButton.setOnAction(event -> { try { createSpreadsheet(); showOpenFileButton(); Settings.saveProperties(); } catch (IOException | BiffException | WriteException ex) { addElement(new WikiLabel("create-file-error")); Session.LOGGER.log(Level.WARNING, "Error occurred during creation of spreadsheet file: {0}", new String[]{ex.getLocalizedMessage()} ); } }); return this; } private void showOpenFileButton() { Hyperlink link = new Hyperlink(Util.text("create-file-open")); TextFlow flow = new TextFlow(new WikiLabel("create-file-success"), link); flow.setTextAlignment(TextAlignment.CENTER); addElement(flow); link.setOnAction(ev -> { try { Desktop.getDesktop().open(Session.FILE); } catch (IOException ex) { Session.LOGGER.log(Level.WARNING, "Cannot open file: {0}", new String[]{ex.getLocalizedMessage()} ); } }); nextButton.linkTo("StartPane", stage, true).setText(Util.text("create-file-back-to-start")); nextButton.setVisible(true); } private void autoSizeColumn(int column, WritableSheet sheet) { CellView cell = sheet.getColumnView(column); cell.setAutosize(true); sheet.setColumnView(column, cell); } private void createSpreadsheet() throws IOException, BiffException, WriteException { File f = new File(Session.DIRECTORY, fileName.getText() + ".xls"); WritableWorkbook workbook = Workbook.createWorkbook(f); createDataSheet(workbook); createTemplateSheet(workbook); workbook.write(); workbook.close(); Session.FILE = f; } /** * * @param workbook * @throws WriteException */ private void createDataSheet(WritableWorkbook workbook) throws WriteException { WritableSheet sheet = workbook.createSheet("Data", 0); // first row (header) int column = 0; for (String variable : Session.VARIABLES) { sheet.addCell(new Label(column++, 0, variable)); } // next rows with path and name int row = 1; for (File file : Session.FILES) { sheet.addCell(new Label(0, row, file.getAbsolutePath())); sheet.addCell(new Label(1, row++, Util.getNameFromFilename(file.getName()))); } if (Session.METHOD.equals("template")) { Template template = Settings.TEMPLATES.get(Session.TEMPLATE); for (TemplateField tf : template.variables) { if (tf.isSelected && !tf.value.isEmpty()) { column = Session.VARIABLES.indexOf(tf.name); row = 1; for (File file : Session.FILES) { sheet.addCell(new Label(column, row++, tf.value)); } } } } column = Session.VARIABLES.indexOf("date"); if (column >= 0 && !Settings.getSetting("exifDate").isEmpty()) { row = 1; for (File file : Session.FILES) { sheet.addCell(new Label(column, row++, getExifDate(file))); } } for (int num = 0; num < sheet.getColumns(); num++) { autoSizeColumn(num, sheet); } } /** * * @param workbook * @throws WriteException */ private void createTemplateSheet(WritableWorkbook workbook) throws WriteException { WritableSheet templateSheet = workbook.createSheet("Template", 1); templateSheet.addCell(new Label(0, 0, "'" + Session.WIKICODE)); // ^^ // leading apostrophe prevents turning wikitext into formula in Excel autoSizeColumn(0, templateSheet); } /** * * @param filePath * @return */ private String getExifDate(File file) { try { Metadata metadata = ImageMetadataReader.readMetadata(file); Directory directory = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class); int dateTag = ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL; if (directory != null && directory.containsTag(dateTag)) { Date date = directory.getDate(dateTag, TimeZone.getDefault()); return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date); } else { return ""; } } catch (ImageProcessingException | IOException ex) { Session.LOGGER.log(Level.INFO, "Exif error for {0}: {1}", new String[]{file.getName(), ex.getLocalizedMessage()} ); return ""; } } }