001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.widgets; 003 004import java.awt.KeyboardFocusManager; 005import java.awt.event.FocusEvent; 006import java.awt.event.FocusListener; 007 008import javax.swing.JTextArea; 009import javax.swing.text.Document; 010 011import org.openstreetmap.josm.gui.MainApplication; 012import org.openstreetmap.josm.gui.MapFrame; 013 014/** 015 * Subclass of {@link JTextArea} that adds a "native" context menu (cut/copy/paste/select all). 016 * @since 5886 017 */ 018public class JosmTextArea extends JTextArea implements FocusListener { 019 020 /** 021 * Constructs a new {@code JosmTextArea}. A default model is set, the initial string 022 * is null, and rows/columns are set to 0. 023 */ 024 public JosmTextArea() { 025 this(null, null, 0, 0); 026 } 027 028 /** 029 * Constructs a new {@code JosmTextArea} with the specified text displayed. 030 * A default model is created and rows/columns are set to 0. 031 * 032 * @param text the text to be displayed, or null 033 */ 034 public JosmTextArea(String text) { 035 this(null, text, 0, 0); 036 } 037 038 /** 039 * Constructs a new {@code JosmTextArea} with the given document model, and defaults 040 * for all of the other arguments (null, 0, 0). 041 * 042 * @param doc the model to use 043 */ 044 public JosmTextArea(Document doc) { 045 this(doc, null, 0, 0); 046 } 047 048 /** 049 * Constructs a new empty {@code JosmTextArea} with the specified number of 050 * rows and columns. A default model is created, and the initial 051 * string is null. 052 * 053 * @param rows the number of rows >= 0 054 * @param columns the number of columns >= 0 055 * @throws IllegalArgumentException if the rows or columns 056 * arguments are negative. 057 */ 058 public JosmTextArea(int rows, int columns) { 059 this(null, null, rows, columns); 060 } 061 062 /** 063 * Constructs a new {@code JosmTextArea} with the specified text and number 064 * of rows and columns. A default model is created. 065 * 066 * @param text the text to be displayed, or null 067 * @param rows the number of rows >= 0 068 * @param columns the number of columns >= 0 069 * @throws IllegalArgumentException if the rows or columns 070 * arguments are negative. 071 */ 072 public JosmTextArea(String text, int rows, int columns) { 073 this(null, text, rows, columns); 074 } 075 076 /** 077 * Constructs a new {@code JosmTextArea} with the specified number of rows 078 * and columns, and the given model. All of the constructors 079 * feed through this constructor. 080 * 081 * @param doc the model to use, or create a default one if null 082 * @param text the text to be displayed, null if none 083 * @param rows the number of rows >= 0 084 * @param columns the number of columns >= 0 085 * @throws IllegalArgumentException if the rows or columns 086 * arguments are negative. 087 */ 088 public JosmTextArea(Document doc, String text, int rows, int columns) { 089 super(doc, text, rows, columns); 090 TextContextualPopupMenu.enableMenuFor(this, true); 091 addFocusListener(this); 092 } 093 094 /** 095 * Restore default behaviour of focus transfer with TAB, overriden by {@link JTextArea}. 096 * @return {@code this} 097 * @since 11308 098 */ 099 public JosmTextArea transferFocusOnTab() { 100 // http://stackoverflow.com/a/525867/2257172 101 setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null); 102 setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null); 103 return this; 104 } 105 106 @Override 107 public void focusGained(FocusEvent e) { 108 MapFrame map = MainApplication.getMap(); 109 if (map != null) { 110 map.keyDetector.setEnabled(false); 111 } 112 } 113 114 @Override 115 public void focusLost(FocusEvent e) { 116 MapFrame map = MainApplication.getMap(); 117 if (map != null) { 118 map.keyDetector.setEnabled(true); 119 } 120 } 121}