From a54ddd174ac8c0f3906625cc77824fe1f382f68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=A9ndez?= Date: Sat, 19 Oct 2019 06:13:57 +0200 Subject: [PATCH 1/4] Add X11 Primary Selection clipboard --- src/main/java/org/jabref/Globals.java | 2 +- .../java/org/jabref/gui/ClipBoardManager.java | 92 ++++++++++++++++--- .../jabref/gui/search/GlobalSearchBar.java | 2 + 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 71466ee47c7..3bc76ac95f1 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -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; diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index 0411f8afd4e..38e3a09e40f 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -1,5 +1,10 @@ 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; @@ -7,9 +12,11 @@ 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; @@ -30,34 +37,56 @@ import org.slf4j.LoggerFactory; public class ClipBoardManager { + 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(); @@ -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 entries) throws IOException { @@ -85,6 +152,7 @@ public void setContent(List entries) throws IOException { String serializedEntries = writer.serializeAll(entries, BibDatabaseMode.BIBTEX); content.put(DragAndDropDataFormats.ENTRIES, serializedEntries); content.putString(serializedEntries); + setContentPrimary(serializedEntries); clipboard.setContent(content); } diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index 6938411b4ad..cd6fbc3fef9 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -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"))); From 150e04435a824e612d388a76fc143233dd74e77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=A9ndez?= Date: Sat, 19 Oct 2019 08:17:01 +0200 Subject: [PATCH 2/4] Add Primary clipboard to text controls in the entry editor --- src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java | 4 ++++ .../java/org/jabref/gui/fieldeditors/EditorTextField.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java index 65a55854974..e30e853266b 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java @@ -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(); @@ -29,6 +31,8 @@ public EditorTextArea(final String text) { // Hide horizontal scrollbar and always wrap text setWrapText(true); + + Globals.clipboardManager.install(this); } @Override diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java index a10583e2774..1fd364daa9f 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java @@ -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(); @@ -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 From 2c492f83162c93128adb88d1e84ec54edce85d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=A9ndez?= Date: Sat, 19 Oct 2019 16:23:57 +0200 Subject: [PATCH 3/4] Update for using singleton with enum and fixing some bugs --- src/main/java/org/jabref/Globals.java | 4 +- .../java/org/jabref/gui/ClipBoardManager.java | 88 +++++++------------ .../gui/fieldeditors/EditorTextArea.java | 9 +- .../gui/fieldeditors/EditorTextField.java | 9 +- .../CitationStyleToClipboardWorker.java | 5 +- .../jabref/gui/search/GlobalSearchBar.java | 8 +- .../CitationStyleToClipboardWorkerTest.java | 3 +- 7 files changed, 60 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 3bc76ac95f1..742ff6b100f 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -56,13 +56,11 @@ public class Globals { /** * Manager for the state of the GUI. */ - - public static ClipBoardManager clipboardManager = ClipBoardManager.getInstance(); - public static StateManager stateManager = new StateManager(); public static ExporterFactory exportFactory; public static CountingUndoManager undoManager = new CountingUndoManager(); public static BibEntryTypesManager entryTypesManager = new BibEntryTypesManager(); + public static ClipBoardManager clipboardManager = ClipBoardManager.INSTANCE; // Key binding preferences private static KeyBindingRepository keyBindingRepository; private static DefaultFileUpdateMonitor fileUpdateMonitor; diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index 38e3a09e40f..3fe645dad9c 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -15,8 +15,6 @@ 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; @@ -36,52 +34,38 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ClipBoardManager { +// Singleton with enum +public enum ClipBoardManager { - public static final DataFormat XML = new DataFormat("application/xml"); + INSTANCE; private static final Logger LOGGER = LoggerFactory.getLogger(ClipBoardManager.class); - // Singleton pattern - private static ClipBoardManager singleton; + private final Clipboard clipboard = Clipboard.getSystemClipboard(); + private final java.awt.datatransfer.Clipboard primary = Toolkit.getDefaultToolkit().getSystemSelection(); + private final ImportFormatReader importFormatReader = Globals.IMPORT_FORMAT_READER; - private final Clipboard clipboard; - private final java.awt.datatransfer.Clipboard primarySelection; - private final ImportFormatReader importFormatReader; - - // Private constructor (singleton) - private ClipBoardManager() { - clipboard = Clipboard.getSystemClipboard(); - primarySelection = Toolkit.getDefaultToolkit().getSystemSelection(); - importFormatReader = Globals.IMPORT_FORMAT_READER; + ClipBoardManager() { } - // Singleton pattern - public synchronized static ClipBoardManager getInstance() { - if (ClipBoardManager.singleton == null) { - ClipBoardManager.singleton = new ClipBoardManager(); + public void watchInput(String newValue) { + if (!newValue.isEmpty()) { + primary.setContents(new StringSelection(newValue), null); } - return ClipBoardManager.singleton; } - // Override clone() method - @Override - public ClipBoardManager clone() { - return null; + public void inputToPrimary(TextInputControl input) { + input.insertText(input.getCaretPosition(), getContentsPrimary()); } - 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()); - } - }); - } + // For activating this functionality in an input, use: + // + // input.selectedTextProperty().addListener((observable, oldValue, newValue) -> watchInput(newValue)); + // input.setOnMouseClicked(event -> { + // if (event.getButton() == MouseButton.MIDDLE) { + // inputToPrimary(input); + // } + // }); /** * Get the String residing on the clipboard. @@ -96,9 +80,9 @@ public String getContents() { return result; } - // X11 Primary Selection + // Get the text from Primary public String getContentsPrimary() { - Transferable contents = primarySelection.getContents(null); + Transferable contents = primary.getContents(null); if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) { try { return (String) contents.getTransferData(DataFlavor.stringFlavor); @@ -109,41 +93,31 @@ public String getContentsPrimary() { return getContents(); } + // Copy from Clipboard to Primary + private void clipboardToPrimary(ClipboardContent content) { + primary.setContents(new StringSelection(content.getString()), null); + } + /** * 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); + clipboardToPrimary(content); } public void setHtmlContent(String html) { final ClipboardContent content = new ClipboardContent(); content.putHtml(html); clipboard.setContent(content); - setContentPrimary(html); + clipboardToPrimary(content); } public void setContent(String string) { final ClipboardContent content = new ClipboardContent(); content.putString(string); clipboard.setContent(content); - setContentPrimary(string); + clipboardToPrimary(content); } public void setContent(List entries) throws IOException { @@ -152,8 +126,8 @@ public void setContent(List entries) throws IOException { String serializedEntries = writer.serializeAll(entries, BibDatabaseMode.BIBTEX); content.put(DragAndDropDataFormats.ENTRIES, serializedEntries); content.putString(serializedEntries); - setContentPrimary(serializedEntries); clipboard.setContent(content); + clipboardToPrimary(content); } public List extractData() { diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java index e30e853266b..49a9d2f5c50 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java @@ -9,6 +9,7 @@ import javafx.fxml.Initializable; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; +import javafx.scene.input.MouseButton; import org.jabref.Globals; @@ -32,7 +33,13 @@ public EditorTextArea(final String text) { // Hide horizontal scrollbar and always wrap text setWrapText(true); - Globals.clipboardManager.install(this); + // Active Primary clipboard + this.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); + this.setOnMouseClicked(event -> { + if (event.getButton() == MouseButton.MIDDLE) { + Globals.clipboardManager.inputToPrimary(this); + } + }); } @Override diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java index 1fd364daa9f..656f7288f52 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java @@ -8,6 +8,7 @@ import javafx.fxml.Initializable; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; +import javafx.scene.input.MouseButton; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; @@ -28,7 +29,13 @@ public EditorTextField(final String text) { setPrefHeight(Double.POSITIVE_INFINITY); HBox.setHgrow(this, Priority.ALWAYS); - Globals.clipboardManager.install(this); + // Active Primary clipboard + this.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); + this.setOnMouseClicked(event -> { + if (event.getButton() == MouseButton.MIDDLE) { + Globals.clipboardManager.inputToPrimary(this); + } + }); } @Override diff --git a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java b/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java index 23a4f056d36..0c1502bd2ac 100644 --- a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java +++ b/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java @@ -6,6 +6,7 @@ import java.util.List; import javafx.scene.input.ClipboardContent; +import javafx.scene.input.DataFormat; import org.jabref.Globals; import org.jabref.gui.BasePanel; @@ -34,6 +35,8 @@ */ public class CitationStyleToClipboardWorker { + public static final DataFormat XML = new DataFormat("application/xml"); + private static final Logger LOGGER = LoggerFactory.getLogger(CitationStyleToClipboardWorker.class); private final BasePanel basePanel; @@ -139,7 +142,7 @@ protected static ClipboardContent processXslFo(List citations) { ClipboardContent content = new ClipboardContent(); content.putString(result); - content.put(ClipBoardManager.XML, result); + content.put(XML, result); return content; } diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index cd6fbc3fef9..74b4c12391c 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -111,7 +111,13 @@ public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) { } }); - Globals.clipboardManager.install(searchField); + // Active Primary clipboard + searchField.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); + searchField.setOnMouseClicked(event -> { + if (event.getButton() == MouseButton.MIDDLE) { + Globals.clipboardManager.inputToPrimary(searchField); + } + }); regularExp = IconTheme.JabRefIcons.REG_EX.asToggleButton(); regularExp.setSelected(searchPreferences.isRegularExpression()); diff --git a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java b/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java index 82501d0e182..513f24e3b7e 100644 --- a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java +++ b/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java @@ -4,7 +4,6 @@ import javafx.scene.input.ClipboardContent; -import org.jabref.gui.ClipBoardManager; import org.jabref.logic.util.OS; import org.junit.jupiter.api.Test; @@ -193,7 +192,7 @@ void processXslFo() throws Exception { ClipboardContent xmlTransferable = CitationStyleToClipboardWorker.processXslFo(Arrays.asList(citation, citation)); - Object actual = xmlTransferable.get(ClipBoardManager.XML); + Object actual = xmlTransferable.get(CitationStyleToClipboardWorker.XML); assertEquals(expected, actual); } From 554e45b2fffc3850523ef8bb7c0969a89c76ca45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=A9ndez?= Date: Sun, 20 Oct 2019 13:41:09 +0200 Subject: [PATCH 4/4] Revert to a non-singleton design, improve setup, and standardize comments --- src/main/java/org/jabref/Globals.java | 2 +- .../java/org/jabref/gui/ClipBoardManager.java | 93 ++++++++++++------- .../gui/fieldeditors/EditorTextArea.java | 11 +-- .../gui/fieldeditors/EditorTextField.java | 11 +-- .../CitationStyleToClipboardWorker.java | 5 +- .../jabref/gui/search/GlobalSearchBar.java | 9 +- .../CitationStyleToClipboardWorkerTest.java | 3 +- 7 files changed, 67 insertions(+), 67 deletions(-) diff --git a/src/main/java/org/jabref/Globals.java b/src/main/java/org/jabref/Globals.java index 742ff6b100f..12531280708 100644 --- a/src/main/java/org/jabref/Globals.java +++ b/src/main/java/org/jabref/Globals.java @@ -60,7 +60,7 @@ public class Globals { public static ExporterFactory exportFactory; public static CountingUndoManager undoManager = new CountingUndoManager(); public static BibEntryTypesManager entryTypesManager = new BibEntryTypesManager(); - public static ClipBoardManager clipboardManager = ClipBoardManager.INSTANCE; + public static ClipBoardManager clipboardManager = new ClipBoardManager(); // Key binding preferences private static KeyBindingRepository keyBindingRepository; private static DefaultFileUpdateMonitor fileUpdateMonitor; diff --git a/src/main/java/org/jabref/gui/ClipBoardManager.java b/src/main/java/org/jabref/gui/ClipBoardManager.java index 3fe645dad9c..64bc6617533 100644 --- a/src/main/java/org/jabref/gui/ClipBoardManager.java +++ b/src/main/java/org/jabref/gui/ClipBoardManager.java @@ -15,6 +15,8 @@ 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; @@ -34,45 +36,54 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// Singleton with enum -public enum ClipBoardManager { +public class ClipBoardManager { - INSTANCE; + public static final DataFormat XML = new DataFormat("application/xml"); private static final Logger LOGGER = LoggerFactory.getLogger(ClipBoardManager.class); - private final Clipboard clipboard = Clipboard.getSystemClipboard(); - private final java.awt.datatransfer.Clipboard primary = Toolkit.getDefaultToolkit().getSystemSelection(); - private final ImportFormatReader importFormatReader = Globals.IMPORT_FORMAT_READER; + private static Clipboard clipboard; + private static java.awt.datatransfer.Clipboard primary; + private static ImportFormatReader importFormatReader; - ClipBoardManager() { + public ClipBoardManager(Clipboard clipboard, java.awt.datatransfer.Clipboard primary, ImportFormatReader importFormatReader) { + ClipBoardManager.clipboard = clipboard; + ClipBoardManager.primary = primary; + ClipBoardManager.importFormatReader = importFormatReader; } - public void watchInput(String newValue) { - if (!newValue.isEmpty()) { - primary.setContents(new StringSelection(newValue), null); - } + public ClipBoardManager() { + this(Clipboard.getSystemClipboard(), Toolkit.getDefaultToolkit().getSystemSelection(), Globals.IMPORT_FORMAT_READER); } - public void inputToPrimary(TextInputControl input) { - input.insertText(input.getCaretPosition(), getContentsPrimary()); + /** + * Add X11 clipboard support to a text input control. + * It is necessary to call this method in every input where you want to use it: + * {@code ClipBoardManager.addX11Support(TextInputControl input);}. + * + * @param input the TextInputControl (e.g., TextField, TextArea, and children) where adding this functionality. + * @see Short summary for X11 clipboards + * @see Longer text over clipboards + */ + public static void addX11Support(TextInputControl input) { + input.selectedTextProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue.isEmpty()) { + primary.setContents(new StringSelection(newValue), null); + } + }); + input.setOnMouseClicked(event -> { + if (event.getButton() == MouseButton.MIDDLE) { + input.insertText(input.getCaretPosition(), getContentsPrimary()); + } + }); } - // For activating this functionality in an input, use: - // - // input.selectedTextProperty().addListener((observable, oldValue, newValue) -> watchInput(newValue)); - // input.setOnMouseClicked(event -> { - // if (event.getButton() == MouseButton.MIDDLE) { - // inputToPrimary(input); - // } - // }); - /** - * Get the String residing on the clipboard. + * Get the String residing on the system clipboard. * * @return any text found on the Clipboard; if none found, return an empty String. */ - public String getContents() { + public static String getContents() { String result = clipboard.getString(); if (result == null) { return ""; @@ -80,8 +91,12 @@ public String getContents() { return result; } - // Get the text from Primary - public String getContentsPrimary() { + /** + * Get the String residing on the primary clipboard. + * + * @return any text found on the primary Clipboard; if none found, try with the system clipboard. + */ + public static String getContentsPrimary() { Transferable contents = primary.getContents(null); if (contents != null && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) { try { @@ -93,31 +108,37 @@ public String getContentsPrimary() { return getContents(); } - // Copy from Clipboard to Primary - private void clipboardToPrimary(ClipboardContent content) { - primary.setContents(new StringSelection(content.getString()), null); - } - /** - * Puts content onto the clipboard. + * Puts content onto the system clipboard. + * + * @param content the ClipboardContent to set as current value of the system clipboard. */ public void setContent(ClipboardContent content) { clipboard.setContent(content); - clipboardToPrimary(content); + setPrimaryClipboardContent(content); + } + + /** + * Puts content onto the primary clipboard. + * + * @param content the ClipboardContent to set as current value of the primary clipboard. + */ + public void setPrimaryClipboardContent(ClipboardContent content) { + primary.setContents(new StringSelection(content.getString()), null); } public void setHtmlContent(String html) { final ClipboardContent content = new ClipboardContent(); content.putHtml(html); clipboard.setContent(content); - clipboardToPrimary(content); + setPrimaryClipboardContent(content); } public void setContent(String string) { final ClipboardContent content = new ClipboardContent(); content.putString(string); clipboard.setContent(content); - clipboardToPrimary(content); + setPrimaryClipboardContent(content); } public void setContent(List entries) throws IOException { @@ -127,7 +148,7 @@ public void setContent(List entries) throws IOException { content.put(DragAndDropDataFormats.ENTRIES, serializedEntries); content.putString(serializedEntries); clipboard.setContent(content); - clipboardToPrimary(content); + setPrimaryClipboardContent(content); } public List extractData() { diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java index 49a9d2f5c50..13a7f7f6ac3 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextArea.java @@ -9,9 +9,8 @@ import javafx.fxml.Initializable; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; -import javafx.scene.input.MouseButton; -import org.jabref.Globals; +import org.jabref.gui.ClipBoardManager; public class EditorTextArea extends javafx.scene.control.TextArea implements Initializable, ContextMenuAddable { @@ -33,13 +32,7 @@ public EditorTextArea(final String text) { // Hide horizontal scrollbar and always wrap text setWrapText(true); - // Active Primary clipboard - this.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); - this.setOnMouseClicked(event -> { - if (event.getButton() == MouseButton.MIDDLE) { - Globals.clipboardManager.inputToPrimary(this); - } - }); + ClipBoardManager.addX11Support(this); } @Override diff --git a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java index 656f7288f52..215083980a8 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java +++ b/src/main/java/org/jabref/gui/fieldeditors/EditorTextField.java @@ -8,11 +8,10 @@ import javafx.fxml.Initializable; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; -import javafx.scene.input.MouseButton; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; -import org.jabref.Globals; +import org.jabref.gui.ClipBoardManager; public class EditorTextField extends javafx.scene.control.TextField implements Initializable, ContextMenuAddable { @@ -29,13 +28,7 @@ public EditorTextField(final String text) { setPrefHeight(Double.POSITIVE_INFINITY); HBox.setHgrow(this, Priority.ALWAYS); - // Active Primary clipboard - this.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); - this.setOnMouseClicked(event -> { - if (event.getButton() == MouseButton.MIDDLE) { - Globals.clipboardManager.inputToPrimary(this); - } - }); + ClipBoardManager.addX11Support(this); } @Override diff --git a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java b/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java index 0c1502bd2ac..23a4f056d36 100644 --- a/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java +++ b/src/main/java/org/jabref/gui/preview/CitationStyleToClipboardWorker.java @@ -6,7 +6,6 @@ import java.util.List; import javafx.scene.input.ClipboardContent; -import javafx.scene.input.DataFormat; import org.jabref.Globals; import org.jabref.gui.BasePanel; @@ -35,8 +34,6 @@ */ public class CitationStyleToClipboardWorker { - public static final DataFormat XML = new DataFormat("application/xml"); - private static final Logger LOGGER = LoggerFactory.getLogger(CitationStyleToClipboardWorker.class); private final BasePanel basePanel; @@ -142,7 +139,7 @@ protected static ClipboardContent processXslFo(List citations) { ClipboardContent content = new ClipboardContent(); content.putString(result); - content.put(XML, result); + content.put(ClipBoardManager.XML, result); return content; } diff --git a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java index 74b4c12391c..9ce56f914b7 100644 --- a/src/main/java/org/jabref/gui/search/GlobalSearchBar.java +++ b/src/main/java/org/jabref/gui/search/GlobalSearchBar.java @@ -34,6 +34,7 @@ import org.jabref.Globals; import org.jabref.gui.BasePanel; +import org.jabref.gui.ClipBoardManager; import org.jabref.gui.JabRefFrame; import org.jabref.gui.StateManager; import org.jabref.gui.autocompleter.AppendPersonNamesStrategy; @@ -111,13 +112,7 @@ public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) { } }); - // Active Primary clipboard - searchField.selectedTextProperty().addListener((observable, oldValue, newValue) -> Globals.clipboardManager.watchInput(newValue)); - searchField.setOnMouseClicked(event -> { - if (event.getButton() == MouseButton.MIDDLE) { - Globals.clipboardManager.inputToPrimary(searchField); - } - }); + ClipBoardManager.addX11Support(searchField); regularExp = IconTheme.JabRefIcons.REG_EX.asToggleButton(); regularExp.setSelected(searchPreferences.isRegularExpression()); diff --git a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java b/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java index 513f24e3b7e..82501d0e182 100644 --- a/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java +++ b/src/test/java/org/jabref/gui/preview/CitationStyleToClipboardWorkerTest.java @@ -4,6 +4,7 @@ import javafx.scene.input.ClipboardContent; +import org.jabref.gui.ClipBoardManager; import org.jabref.logic.util.OS; import org.junit.jupiter.api.Test; @@ -192,7 +193,7 @@ void processXslFo() throws Exception { ClipboardContent xmlTransferable = CitationStyleToClipboardWorker.processXslFo(Arrays.asList(citation, citation)); - Object actual = xmlTransferable.get(CitationStyleToClipboardWorker.XML); + Object actual = xmlTransferable.get(ClipBoardManager.XML); assertEquals(expected, actual); }