Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add X11 Primary Selection clipboard support #5482

Merged
merged 4 commits into from
Oct 27, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class Globals {
* Manager for the state of the GUI.
*/

public static ClipBoardManager clipboardManager = new ClipBoardManager();
public static ClipBoardManager clipboardManager = ClipBoardManager.getInstance();

public static StateManager stateManager = new StateManager();
public static ExporterFactory exportFactory;
Expand Down
92 changes: 80 additions & 12 deletions src/main/java/org/jabref/gui/ClipBoardManager.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package org.jabref.gui;

import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javafx.scene.control.TextInputControl;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.MouseButton;

import org.jabref.Globals;
import org.jabref.logic.bibtex.BibEntryWriter;
Expand All @@ -30,34 +37,56 @@
import org.slf4j.LoggerFactory;

public class ClipBoardManager {
davidemdot marked this conversation as resolved.
Show resolved Hide resolved

public static final DataFormat XML = new DataFormat("application/xml");

private static final Logger LOGGER = LoggerFactory.getLogger(ClipBoardManager.class);

// Singleton pattern
private static ClipBoardManager singleton;

private final Clipboard clipboard;
private final java.awt.datatransfer.Clipboard primarySelection;
private final ImportFormatReader importFormatReader;

public ClipBoardManager() {
this(Clipboard.getSystemClipboard(), Globals.IMPORT_FORMAT_READER);
// Private constructor (singleton)
private ClipBoardManager() {
clipboard = Clipboard.getSystemClipboard();
primarySelection = Toolkit.getDefaultToolkit().getSystemSelection();
importFormatReader = Globals.IMPORT_FORMAT_READER;
}

public ClipBoardManager(Clipboard clipboard, ImportFormatReader importFormatReader) {
this.clipboard = clipboard;
this.importFormatReader = importFormatReader;
// Singleton pattern
public synchronized static ClipBoardManager getInstance() {
if (ClipBoardManager.singleton == null) {
ClipBoardManager.singleton = new ClipBoardManager();
}
return ClipBoardManager.singleton;
}

/**
* Puts content onto the clipboard.
*/
public void setContent(ClipboardContent content) {
clipboard.setContent(content);
// Override clone() method
@Override
public ClipBoardManager clone() {
return null;
}

public void install(TextInputControl field) {
field.selectedTextProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue.isEmpty()) {
setContentPrimary(newValue);
}
});
field.setOnMouseClicked(event -> {
if (event.getButton() == MouseButton.MIDDLE) {
field.insertText(field.getCaretPosition(), getContentsPrimary());
}
});
}

/**
* Get the String residing on the clipboard.
*
* @return any text found on the Clipboard; if none found, return an
* empty String.
* @return any text found on the Clipboard; if none found, return an empty String.
*/
public String getContents() {
String result = clipboard.getString();
Expand All @@ -67,16 +96,54 @@ public String getContents() {
return result;
}

// X11 Primary Selection
public String getContentsPrimary() {
Transferable contents = primarySelection.getContents(null);
if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
return (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException | IOException e) {
LOGGER.warn(e.getMessage());
}
}
return getContents();
}

/**
* Puts content onto the clipboard.
*/
public void setContent(ClipboardContent content) {
clipboard.setContent(content);

// Copy to X11 Primary Clipboard
if (content.hasHtml()) {
setContentPrimary(content.getHtml());
} else if (content.hasRtf()) {
setContentPrimary(content.getRtf());
} else if (content.hasUrl()) {
setContentPrimary(content.getUrl());
} else if (content.hasString()) {
setContentPrimary(content.getString());
}
}

// X11 Primary Selection
public void setContentPrimary(String string) {
primarySelection.setContents(new StringSelection(string), null);
}

public void setHtmlContent(String html) {
final ClipboardContent content = new ClipboardContent();
content.putHtml(html);
clipboard.setContent(content);
setContentPrimary(html);
}

public void setContent(String string) {
final ClipboardContent content = new ClipboardContent();
content.putString(string);
clipboard.setContent(content);
setContentPrimary(string);
}

public void setContent(List<BibEntry> entries) throws IOException {
Expand All @@ -85,6 +152,7 @@ public void setContent(List<BibEntry> entries) throws IOException {
String serializedEntries = writer.serializeAll(entries, BibDatabaseMode.BIBTEX);
content.put(DragAndDropDataFormats.ENTRIES, serializedEntries);
content.putString(serializedEntries);
setContentPrimary(serializedEntries);
clipboard.setContent(content);
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;

import org.jabref.Globals;

public class EditorTextArea extends javafx.scene.control.TextArea implements Initializable, ContextMenuAddable {

private final ContextMenu contextMenu = new ContextMenu();
Expand All @@ -29,6 +31,8 @@ public EditorTextArea(final String text) {

// Hide horizontal scrollbar and always wrap text
setWrapText(true);

Globals.clipboardManager.install(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;

import org.jabref.Globals;

public class EditorTextField extends javafx.scene.control.TextField implements Initializable, ContextMenuAddable {

private final ContextMenu contextMenu = new ContextMenu();
Expand All @@ -25,6 +27,8 @@ public EditorTextField(final String text) {
// Always fill out all the available space
setPrefHeight(Double.POSITIVE_INFINITY);
HBox.setHgrow(this, Priority.ALWAYS);

Globals.clipboardManager.install(this);
}

@Override
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/jabref/gui/search/GlobalSearchBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) {
}
});

Globals.clipboardManager.install(searchField);

regularExp = IconTheme.JabRefIcons.REG_EX.asToggleButton();
regularExp.setSelected(searchPreferences.isRegularExpression());
regularExp.setTooltip(new Tooltip(Localization.lang("regular expression")));
Expand Down