1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.lwawt; 28 29 import java.awt.Component; 30 import java.awt.Cursor; 31 import java.awt.Dimension; 32 import java.awt.Point; 33 import java.awt.TextArea; 34 import java.awt.event.TextEvent; 35 import java.awt.peer.TextAreaPeer; 36 37 import javax.swing.JScrollBar; 38 import javax.swing.JScrollPane; 39 import javax.swing.JTextArea; 40 import javax.swing.ScrollPaneConstants; 41 import javax.swing.text.Document; 42 import javax.swing.text.JTextComponent; 43 44 final class LWTextAreaPeer 45 extends LWTextComponentPeer<TextArea, LWTextAreaPeer.ScrollableJTextArea> 46 implements TextAreaPeer { 47 48 private static final int DEFAULT_COLUMNS = 60; 49 private static final int DEFAULT_ROWS = 10; 50 51 LWTextAreaPeer(final TextArea target, 52 final PlatformComponent platformComponent) { 53 super(target, platformComponent); 54 } 55 56 @Override 57 protected ScrollableJTextArea createDelegate() { 58 return new ScrollableJTextArea(); 59 } 60 61 @Override 62 void initializeImpl() { 63 super.initializeImpl(); 64 final int visibility = getTarget().getScrollbarVisibility(); 65 synchronized (getDelegateLock()) { 66 setScrollBarVisibility(visibility); 67 } 68 } 69 70 @Override 71 JTextComponent getTextComponent() { 72 return getDelegate().getView(); 73 } 74 75 @Override 76 protected Cursor getCursor(final Point p) { 77 final boolean isContains; 78 synchronized (getDelegateLock()) { 79 isContains = getDelegate().getViewport().getBounds().contains(p); 80 } 81 return isContains ? super.getCursor(p) : null; 82 } 83 84 @Override 85 protected Component getDelegateFocusOwner() { 86 return getTextComponent(); 87 } 88 89 @Override 90 public Dimension getMinimumSize() { 91 return getMinimumSize(DEFAULT_ROWS, DEFAULT_COLUMNS); 92 } 93 94 @Override 95 public Dimension getMinimumSize(final int rows, final int columns) { 96 return getPreferredSize(rows, columns); 97 } 98 99 @Override 100 public Dimension getPreferredSize(final int rows, final int columns) { 101 final Dimension size = super.getPreferredSize(rows, columns); 102 synchronized (getDelegateLock()) { 103 final JScrollBar vbar = getDelegate().getVerticalScrollBar(); 104 final JScrollBar hbar = getDelegate().getHorizontalScrollBar(); 105 final int scrollbarW = vbar != null ? vbar.getWidth() : 0; 106 final int scrollbarH = hbar != null ? hbar.getHeight() : 0; 107 return new Dimension(size.width + scrollbarW, 108 size.height + scrollbarH); 109 } 110 } 111 112 @Override 113 public void insert(final String text, final int pos) { 114 final ScrollableJTextArea pane = getDelegate(); 115 synchronized (getDelegateLock()) { 116 final JTextArea area = pane.getView(); 117 final boolean doScroll = pos >= area.getDocument().getLength() 118 && area.getDocument().getLength() != 0; 119 area.insert(text, pos); 120 revalidate(); 121 if (doScroll) { 122 final JScrollBar vbar = pane.getVerticalScrollBar(); 123 if (vbar != null) { 124 vbar.setValue(vbar.getMaximum() - vbar.getVisibleAmount()); 125 } 126 } 127 } 128 repaintPeer(); 129 } 130 131 @Override 132 public void setText(final String l) { 133 // Please note that we do not want to post an event 134 // if TextArea.setText() replaces an empty text by an empty text, 135 // that is, if component's text remains unchanged. 136 if (!l.isEmpty() || getTextComponent().getDocument().getLength() != 0) { 137 super.setText(l); 138 } 139 } 140 141 @Override 142 public void replaceRange(final String text, final int start, 143 final int end) { 144 synchronized (getDelegateLock()) { 145 // JTextArea.replaceRange() posts two different events. 146 // Since we make no differences between text events, 147 // the document listener has to be disabled while 148 // JTextArea.replaceRange() is called. 149 final Document document = getTextComponent().getDocument(); 150 document.removeDocumentListener(this); 151 getDelegate().getView().replaceRange(text, start, end); 152 revalidate(); 153 postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); 154 document.addDocumentListener(this); 155 } 156 repaintPeer(); 157 } 158 159 private void setScrollBarVisibility(final int visibility) { 160 final ScrollableJTextArea pane = getDelegate(); 161 final JTextArea view = pane.getView(); 162 view.setLineWrap(false); 163 164 switch (visibility) { 165 case TextArea.SCROLLBARS_NONE: 166 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 167 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 168 view.setLineWrap(true); 169 break; 170 case TextArea.SCROLLBARS_VERTICAL_ONLY: 171 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 172 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 173 view.setLineWrap(true); 174 break; 175 case TextArea.SCROLLBARS_HORIZONTAL_ONLY: 176 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 177 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 178 break; 179 default: 180 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 181 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 182 break; 183 } 184 } 185 186 @SuppressWarnings("serial") 187 final class ScrollableJTextArea extends JScrollPane { 188 189 ScrollableJTextArea() { 190 super(); 191 getViewport().setView(new JTextAreaDelegate()); 192 } 193 194 public JTextArea getView() { 195 return (JTextArea) getViewport().getView(); 196 } 197 198 @Override 199 public void setEnabled(final boolean enabled) { 200 getViewport().getView().setEnabled(enabled); 201 super.setEnabled(enabled); 202 } 203 204 @SuppressWarnings("serial") 205 private final class JTextAreaDelegate extends JTextArea { 206 207 // Empty non private constructor was added because access to this 208 // class shouldn't be emulated by a synthetic accessor method. 209 JTextAreaDelegate() { 210 super(); 211 } 212 213 @Override 214 public void replaceSelection(String content) { 215 getDocument().removeDocumentListener(LWTextAreaPeer.this); 216 super.replaceSelection(content); 217 // post only one text event in this case 218 postTextEvent(); 219 getDocument().addDocumentListener(LWTextAreaPeer.this); 220 } 221 222 @Override 223 public boolean hasFocus() { 224 return getTarget().hasFocus(); 225 } 226 227 @Override 228 public Point getLocationOnScreen() { 229 return LWTextAreaPeer.this.getLocationOnScreen(); 230 } 231 } 232 } 233 }