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 replaceRange(final String text, final int start, 133 final int end) { 134 synchronized (getDelegateLock()) { 135 // JTextArea.replaceRange() posts two different events. 136 // Since we make no differences between text events, 137 // the document listener has to be disabled while 138 // JTextArea.replaceRange() is called. 139 final Document document = getTextComponent().getDocument(); 140 document.removeDocumentListener(this); 141 getDelegate().getView().replaceRange(text, start, end); 142 revalidate(); 143 postEvent(new TextEvent(getTarget(), TextEvent.TEXT_VALUE_CHANGED)); 144 document.addDocumentListener(this); 145 } 146 repaintPeer(); 147 } 148 149 private void setScrollBarVisibility(final int visibility) { 150 final ScrollableJTextArea pane = getDelegate(); 151 final JTextArea view = pane.getView(); 152 view.setLineWrap(false); 153 154 switch (visibility) { 155 case TextArea.SCROLLBARS_NONE: 156 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 157 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 158 view.setLineWrap(true); 159 break; 160 case TextArea.SCROLLBARS_VERTICAL_ONLY: 161 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 162 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 163 view.setLineWrap(true); 164 break; 165 case TextArea.SCROLLBARS_HORIZONTAL_ONLY: 166 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 167 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 168 break; 169 default: 170 pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 171 pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 172 break; 173 } 174 } 175 176 @SuppressWarnings("serial") 177 final class ScrollableJTextArea extends JScrollPane { 178 179 ScrollableJTextArea() { 180 super(); 181 getViewport().setView(new JTextAreaDelegate()); 182 } 183 184 public JTextArea getView() { 185 return (JTextArea) getViewport().getView(); 186 } 187 188 @Override 189 public void setEnabled(final boolean enabled) { 190 getViewport().getView().setEnabled(enabled); 191 super.setEnabled(enabled); 192 } 193 194 @SuppressWarnings("serial") 195 private final class JTextAreaDelegate extends JTextArea { 196 197 // Empty non private constructor was added because access to this 198 // class shouldn't be emulated by a synthetic accessor method. 199 JTextAreaDelegate() { 200 super(); 201 } 202 203 @Override 204 public void replaceSelection(String content) { 205 getDocument().removeDocumentListener(LWTextAreaPeer.this); 206 super.replaceSelection(content); 207 // post only one text event in this case 208 postTextEvent(); 209 getDocument().addDocumentListener(LWTextAreaPeer.this); 210 } 211 212 @Override 213 public boolean hasFocus() { 214 return getTarget().hasFocus(); 215 } 216 217 @Override 218 public Point getLocationOnScreen() { 219 return LWTextAreaPeer.this.getLocationOnScreen(); 220 } 221 } 222 } 223 }