/*
* Copyright (c) 1998-2017 by Richard A. Wilkes. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, version 2.0. If a copy of the MPL was not distributed with
* this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This Source Code Form is "Incompatible With Secondary Licenses", as
* defined by the Mozilla Public License, version 2.0.
*/
package com.trollworks.gcs.menu.item;
import com.trollworks.gcs.common.HasSourceReference;
import com.trollworks.gcs.library.LibraryExplorerDockable;
import com.trollworks.gcs.pdfview.PdfDockable;
import com.trollworks.gcs.pdfview.PdfRef;
import com.trollworks.toolkit.annotation.Localize;
import com.trollworks.toolkit.collections.ReverseListIterator;
import com.trollworks.toolkit.ui.Selection;
import com.trollworks.toolkit.ui.menu.Command;
import com.trollworks.toolkit.ui.widget.StdFileDialog;
import com.trollworks.toolkit.ui.widget.outline.Outline;
import com.trollworks.toolkit.ui.widget.outline.OutlineModel;
import com.trollworks.toolkit.ui.widget.outline.Row;
import com.trollworks.toolkit.utility.FileType;
import com.trollworks.toolkit.utility.Localization;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import javax.swing.filechooser.FileNameExtensionFilter;
/** Provides the "Open Page Reference" command. */
public class OpenPageReferenceCommand extends Command {
@Localize("Open Page Reference")
private static String OPEN_PAGE_REFERENCE;
@Localize("Open Each Page Reference")
private static String OPEN_EACH_PAGE_REFERENCE;
@Localize("Locate the PDF file for the prefix \"%s\"")
private static String LOCATE_PDF;
@Localize("PDF File")
private static String PDF_FILE;
static {
Localization.initialize();
}
/** The singleton {@link OpenPageReferenceCommand} for opening a single page reference. */
public static final OpenPageReferenceCommand OPEN_ONE_INSTANCE = new OpenPageReferenceCommand(OPEN_PAGE_REFERENCE, "OpenPageReference", KeyEvent.VK_G, COMMAND_MODIFIER); //$NON-NLS-1$
/** The singleton {@link OpenPageReferenceCommand} for opening all page references. */
public static final OpenPageReferenceCommand OPEN_EACH_INSTANCE = new OpenPageReferenceCommand(OPEN_EACH_PAGE_REFERENCE, "OpenEachPageReferences", KeyEvent.VK_G, SHIFTED_COMMAND_MODIFIER); //$NON-NLS-1$
private OpenPageReferenceCommand(String title, String cmd, int key, int modifiers) {
super(title, cmd, key, modifiers);
}
@Override
public void adjust() {
setEnabled(!getReferences(getTarget()).isEmpty());
}
@Override
public void actionPerformed(ActionEvent event) {
HasSourceReference target = getTarget();
if (target != null) {
List<String> references = getReferences(target);
if (!references.isEmpty()) {
String highlight = target.getReferenceHighlight();
if (this == OPEN_ONE_INSTANCE) {
openReference(references.get(0), highlight);
} else {
for (String one : new ReverseListIterator<>(references)) {
openReference(one, highlight);
}
}
}
}
}
public static void openReference(String reference, String highlight) {
int i = reference.length() - 1;
while (i >= 0) {
char ch = reference.charAt(i);
if (ch >= '0' && ch <= '9') {
i--;
} else {
i++;
break;
}
}
if (i > 0) {
String id = reference.substring(0, i);
try {
int page = Integer.parseInt(reference.substring(i));
PdfRef ref = PdfRef.lookup(id, true);
if (ref == null) {
File file = StdFileDialog.showOpenDialog(getFocusOwner(), String.format(LOCATE_PDF, id), new FileNameExtensionFilter(PDF_FILE, FileType.PDF_EXTENSION));
if (file != null) {
ref = new PdfRef(id, file, 0);
ref.save();
}
}
if (ref != null) {
Path path = ref.getFile().toPath();
LibraryExplorerDockable library = LibraryExplorerDockable.get();
PdfDockable dockable = (PdfDockable) library.getDockableFor(path);
if (dockable != null) {
dockable.goToPage(ref, page, highlight);
dockable.getDockContainer().setCurrentDockable(dockable);
} else {
dockable = new PdfDockable(ref, page, highlight);
library.dockPdf(dockable);
library.open(path);
}
}
} catch (NumberFormatException nfex) {
// Ignore
}
}
}
private static HasSourceReference getTarget() {
HasSourceReference ref = null;
Component comp = getFocusOwner();
if (comp instanceof Outline) {
OutlineModel model = ((Outline) comp).getModel();
if (model.hasSelection()) {
Selection selection = model.getSelection();
if (selection.getCount() == 1) {
Row row = model.getFirstSelectedRow();
if (row instanceof HasSourceReference) {
ref = (HasSourceReference) row;
}
}
}
}
return ref;
}
private static List<String> getReferences(HasSourceReference ref) {
List<String> list = new ArrayList<>();
if (ref != null) {
String[] refs = ref.getReference().split("[,;]"); //$NON-NLS-1$
if (refs.length > 0) {
for (String one : refs) {
String trimmed = one.trim();
if (!trimmed.isEmpty()) {
list.add(trimmed);
}
}
}
}
return list;
}
}