You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InputTextFramePasteAction.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2006-2017 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  5. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
  7. * permit persons to whom the Software is furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
  10. * Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  14. * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  15. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. */
  17. package com.dmdirc.addons.ui_swing.components.frames;
  18. import com.dmdirc.addons.ui_swing.components.inputfields.SwingInputField;
  19. import com.dmdirc.addons.ui_swing.dialogs.paste.PasteDialogFactory;
  20. import com.dmdirc.events.eventbus.EventBus;
  21. import com.dmdirc.interfaces.WindowModel;
  22. import java.awt.Toolkit;
  23. import java.awt.Window;
  24. import java.awt.datatransfer.Clipboard;
  25. import java.awt.datatransfer.DataFlavor;
  26. import java.awt.datatransfer.UnsupportedFlavorException;
  27. import java.awt.event.ActionEvent;
  28. import java.io.IOException;
  29. import javax.swing.AbstractAction;
  30. import org.slf4j.Logger;
  31. import org.slf4j.LoggerFactory;
  32. import static com.dmdirc.util.LogUtils.USER_ERROR;
  33. /**
  34. * Paste action for input frames.
  35. */
  36. public final class InputTextFramePasteAction extends AbstractAction {
  37. private static final Logger LOG = LoggerFactory.getLogger(InputTextFramePasteAction.class);
  38. /** A version number for this class. */
  39. private static final long serialVersionUID = 1;
  40. /** Clipboard to paste from. */
  41. private final Clipboard clipboard;
  42. /** Text component to be acted upon. */
  43. private final InputTextFrame inputFrame;
  44. /** Event bus to post events to. */
  45. private final EventBus eventBus;
  46. /** Swing input field. */
  47. private final SwingInputField inputField;
  48. /** Frame container. */
  49. private final WindowModel container;
  50. /** Paste dialog factory. */
  51. private final PasteDialogFactory pasteDialogFactory;
  52. /** Window to parent the dialog on. */
  53. private final Window window;
  54. /**
  55. * Instantiates a new paste action.
  56. *
  57. * @param clipboard Clipboard to paste from
  58. * @param inputFrame Component to be acted upon
  59. */
  60. public InputTextFramePasteAction(final InputTextFrame inputFrame,
  61. final SwingInputField inputField,
  62. final WindowModel container,
  63. final Clipboard clipboard,
  64. final EventBus eventBus,
  65. final PasteDialogFactory pasteDialogFactory,
  66. final Window window) {
  67. super("Paste");
  68. this.clipboard = clipboard;
  69. this.inputFrame = inputFrame;
  70. this.eventBus = eventBus;
  71. this.inputField = inputField;
  72. this.container = container;
  73. this.pasteDialogFactory = pasteDialogFactory;
  74. this.window = window;
  75. }
  76. @Override
  77. public void actionPerformed(final ActionEvent e) {
  78. //wrap in try and catch for when clipboard doesn't exist
  79. //only seems to happen on linux and I couldnt see an obvious JVM bug
  80. try {
  81. if (!clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
  82. return;
  83. }
  84. } catch (final IllegalStateException ex) {
  85. LOG.info(USER_ERROR, "Unable to paste from clipboard.", ex);
  86. return;
  87. }
  88. try {
  89. //get the contents of the input field and combine it with the
  90. //clipboard
  91. doPaste((String) Toolkit.getDefaultToolkit()
  92. .getSystemClipboard().getData(DataFlavor.stringFlavor));
  93. } catch (final IOException ex) {
  94. LOG.info(USER_ERROR, "Unable to get clipboard contents: {}",
  95. ex.getMessage(), ex);
  96. } catch (final UnsupportedFlavorException ex) {
  97. LOG.info(USER_ERROR, "Unsupported clipboard type: {}",
  98. ex.getMessage(), ex);
  99. }
  100. }
  101. /**
  102. * Pastes the specified content into the input area.
  103. *
  104. * @param clipboard The contents of the clipboard to be pasted
  105. *
  106. * @since 0.6.3m1
  107. */
  108. public void doPaste(final String clipboard) {
  109. final String inputFieldText = inputField.getText();
  110. //Get the text that would result from the paste (inputfield
  111. //- selection + clipboard)
  112. final String text = inputFieldText.substring(0, inputField.getSelectionStart())
  113. + clipboard + inputFieldText.substring(inputField.getSelectionEnd());
  114. final String[] clipboardLines = getSplitLine(text);
  115. //check theres something to paste
  116. if (clipboardLines.length > 1) {
  117. //Clear the input field
  118. inputField.setText("");
  119. final Integer pasteTrigger = container.getConfigManager().
  120. getOptionInt("ui", "pasteProtectionLimit", false);
  121. //check whether the number of lines is over the limit
  122. if (pasteTrigger != null && container.getInputModel().get().getNumLines(text) >
  123. pasteTrigger) {
  124. //show the multi line paste dialog
  125. pasteDialogFactory.getPasteDialog(inputFrame, text, window).displayOrRequestFocus();
  126. } else {
  127. //send the lines
  128. for (final String clipboardLine : clipboardLines) {
  129. inputFrame.getContainer().getInputModel()
  130. .ifPresent(im -> im.sendLine(clipboardLine));
  131. }
  132. }
  133. } else {
  134. //put clipboard text in input field
  135. inputField.replaceSelection(clipboard);
  136. }
  137. }
  138. /**
  139. * Splits the line on all line endings.
  140. *
  141. * @param line Line that will be split
  142. *
  143. * @return Split line array
  144. */
  145. private String[] getSplitLine(final String line) {
  146. return line.replace("\r\n", "\n").replace('\r', '\n').split("\n");
  147. }
  148. @Override
  149. @SuppressWarnings("PMD.AvoidCatchingNPE")
  150. public boolean isEnabled() {
  151. try {
  152. return clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor);
  153. } catch (NullPointerException | IllegalStateException ex) { //https://bugs.openjdk.java.net/browse/JDK-7000965
  154. return false;
  155. }
  156. }
  157. }